home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 6 / CU Amiga Magazine's Super CD-ROM 06 (1996)(EMAP Images)(GB)(Track 1 of 4)[!][issue 1997-01].iso / cucd / prog / gnu-c / src / gcc-2.7.0-amiga / config / m68k / lb1sf68.asm < prev    next >
Assembly Source File  |  1995-06-15  |  81KB  |  2,977 lines

  1. /* libgcc1 routines for 68000 w/o floating-point hardware. */
  2. /* Copyright (C) 1994 Free Software Foundation, Inc.
  3.  
  4. This file is free software; you can redistribute it and/or modify it
  5. under the terms of the GNU General Public License as published by the
  6. Free Software Foundation; either version 2, or (at your option) any
  7. later version.
  8.  
  9. In addition to the permissions in the GNU General Public License, the
  10. Free Software Foundation gives you unlimited permission to link the
  11. compiled version of this file with other programs, and to distribute
  12. those programs without any restriction coming from the use of this
  13. file.  (The General Public License restrictions do apply in other
  14. respects; for example, they cover modification of the file, and
  15. distribution when not linked into another program.)
  16.  
  17. This file is distributed in the hope that it will be useful, but
  18. WITHOUT ANY WARRANTY; without even the implied warranty of
  19. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  20. General Public License for more details.
  21.  
  22. You should have received a copy of the GNU General Public License
  23. along with this program; see the file COPYING.  If not, write to
  24. the Free Software Foundation, 59 Temple Place - Suite 330,
  25. Boston, MA 02111-1307, USA.  */
  26.  
  27. /* As a special exception, if you link this library with files
  28.    compiled with GCC to produce an executable, this does not cause
  29.    the resulting executable to be covered by the GNU General Public License.
  30.    This exception does not however invalidate any other reasons why
  31.    the executable file might be covered by the GNU General Public License.  */
  32.  
  33. /* Use this one for any 680x0; assumes no floating point hardware.
  34.    The trailing " '" appearing on some lines is for ANSI preprocessors.  Yuk.
  35.    Some of this code comes from MINIX, via the folks at ericsson.
  36.    D. V. Henkel-Wallace (gumby@cygnus.com) Fete Bastille, 1992
  37. */
  38.  
  39. /* These are predefined by new versions of GNU cpp.  */
  40.  
  41. #ifndef __USER_LABEL_PREFIX__
  42. #define __USER_LABEL_PREFIX__ _
  43. #endif
  44.  
  45. #ifndef __REGISTER_PREFIX__
  46. #define __REGISTER_PREFIX__
  47. #endif
  48.  
  49. #ifndef __IMMEDIATE_PREFIX__
  50. #define __IMMEDIATE_PREFIX__ #
  51. #endif
  52.  
  53. /* ANSI concatenation macros.  */
  54.  
  55. #define CONCAT1(a, b) CONCAT2(a, b)
  56. #define CONCAT2(a, b) a ## b
  57.  
  58. /* Use the right prefix for global labels.  */
  59.  
  60. #define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
  61.  
  62. /* Use the right prefix for registers.  */
  63.  
  64. #define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
  65.  
  66. /* Use the right prefix for immediate values.  */
  67.  
  68. #define IMM(x) CONCAT1 (__IMMEDIATE_PREFIX__, x)
  69.  
  70. #define d0 REG (d0)
  71. #define d1 REG (d1)
  72. #define d2 REG (d2)
  73. #define d3 REG (d3)
  74. #define d4 REG (d4)
  75. #define d5 REG (d5)
  76. #define d6 REG (d6)
  77. #define d7 REG (d7)
  78. #define a0 REG (a0)
  79. #define a1 REG (a1)
  80. #define a2 REG (a2)
  81. #define a3 REG (a3)
  82. #define a4 REG (a4)
  83. #define a5 REG (a5)
  84. #define a6 REG (a6)
  85. #define fp REG (fp)
  86. #define sp REG (sp)
  87.  
  88. #ifdef L_floatex
  89.  
  90. | This is an attempt at a decent floating point (single, double and 
  91. | extended double) code for the GNU C compiler. It should be easy to
  92. | adapt to other compilers (but beware of the local labels!).
  93.  
  94. | Starting date: 21 October, 1990
  95.  
  96. | It is convenient to introduce the notation (s,e,f) for a floating point
  97. | number, where s=sign, e=exponent, f=fraction. We will call a floating
  98. | point number fpn to abbreviate, independently of the precision.
  99. | Let MAX_EXP be in each case the maximum exponent (255 for floats, 1023 
  100. | for doubles and 16383 for long doubles). We then have the following 
  101. | different cases:
  102. |  1. Normalized fpns have 0 < e < MAX_EXP. They correspond to 
  103. |     (-1)^s x 1.f x 2^(e-bias-1).
  104. |  2. Denormalized fpns have e=0. They correspond to numbers of the form
  105. |     (-1)^s x 0.f x 2^(-bias).
  106. |  3. +/-INFINITY have e=MAX_EXP, f=0.
  107. |  4. Quiet NaN (Not a Number) have all bits set.
  108. |  5. Signaling NaN (Not a Number) have s=0, e=MAX_EXP, f=1.
  109.  
  110. |=============================================================================
  111. |                                  exceptions
  112. |=============================================================================
  113.  
  114. | This is the floating point condition code register (_fpCCR):
  115. |
  116. | struct {
  117. |   short _exception_bits;    
  118. |   short _trap_enable_bits;    
  119. |   short _sticky_bits;
  120. |   short _rounding_mode;
  121. |   short _format;
  122. |   short _last_operation;
  123. |   union {
  124. |     float sf;
  125. |     double df;
  126. |   } _operand1;
  127. |   union {
  128. |     float sf;
  129. |     double df;
  130. |   } _operand2;
  131. | } _fpCCR;
  132.  
  133.     .data
  134.     .even
  135.  
  136.     .globl    SYM (_fpCCR)
  137.     
  138. SYM (_fpCCR):
  139. __exception_bits:
  140.     .word    0
  141. __trap_enable_bits:
  142.     .word    0
  143. __sticky_bits:
  144.     .word    0
  145. __rounding_mode:
  146.     .word    ROUND_TO_NEAREST
  147. __format:
  148.     .word    NIL
  149. __last_operation:
  150.     .word    NOOP
  151. __operand1:
  152.     .long    0
  153.     .long    0
  154. __operand2:
  155.     .long     0
  156.     .long    0
  157.  
  158. | Offsets:
  159. EBITS  = __exception_bits - SYM (_fpCCR)
  160. TRAPE  = __trap_enable_bits - SYM (_fpCCR)
  161. STICK  = __sticky_bits - SYM (_fpCCR)
  162. ROUND  = __rounding_mode - SYM (_fpCCR)
  163. FORMT  = __format - SYM (_fpCCR)
  164. LASTO  = __last_operation - SYM (_fpCCR)
  165. OPER1  = __operand1 - SYM (_fpCCR)
  166. OPER2  = __operand2 - SYM (_fpCCR)
  167.  
  168. | The following exception types are supported:
  169. INEXACT_RESULT         = 0x0001
  170. UNDERFLOW         = 0x0002
  171. OVERFLOW         = 0x0004
  172. DIVIDE_BY_ZERO         = 0x0008
  173. INVALID_OPERATION     = 0x0010
  174.  
  175. | The allowed rounding modes are:
  176. UNKNOWN           = -1
  177. ROUND_TO_NEAREST  = 0 | round result to nearest representable value
  178. ROUND_TO_ZERO     = 1 | round result towards zero
  179. ROUND_TO_PLUS     = 2 | round result towards plus infinity
  180. ROUND_TO_MINUS    = 3 | round result towards minus infinity
  181.  
  182. | The allowed values of format are:
  183. NIL          = 0
  184. SINGLE_FLOAT = 1
  185. DOUBLE_FLOAT = 2
  186. LONG_FLOAT   = 3
  187.  
  188. | The allowed values for the last operation are:
  189. NOOP         = 0
  190. ADD          = 1
  191. MULTIPLY     = 2
  192. DIVIDE       = 3
  193. NEGATE       = 4
  194. COMPARE      = 5
  195. EXTENDSFDF   = 6
  196. TRUNCDFSF    = 7
  197.  
  198. |=============================================================================
  199. |                           __clear_sticky_bits
  200. |=============================================================================
  201.  
  202. | The sticky bits are normally not cleared (thus the name), whereas the 
  203. | exception type and exception value reflect the last computation. 
  204. | This routine is provided to clear them (you can also write to _fpCCR,
  205. | since it is globally visible).
  206.  
  207.     .globl  SYM (__clear_sticky_bit)
  208.  
  209.     .text
  210.     .even
  211.  
  212. | void __clear_sticky_bits(void);
  213. SYM (__clear_sticky_bit):        
  214.     lea    SYM (_fpCCR),a0
  215.     movew    IMM (0),a0@(STICK)
  216.     rts
  217.  
  218. |=============================================================================
  219. |                           $_exception_handler
  220. |=============================================================================
  221.  
  222.     .globl  $_exception_handler
  223.  
  224.     .text
  225.     .even
  226.  
  227. | This is the common exit point if an exception occurs.
  228. | NOTE: it is NOT callable from C!
  229. | It expects the exception type in d7, the format (SINGLE_FLOAT,
  230. | DOUBLE_FLOAT or LONG_FLOAT) in d6, and the last operation code in d5.
  231. | It sets the corresponding exception and sticky bits, and the format. 
  232. | Depending on the format if fills the corresponding slots for the 
  233. | operands which produced the exception (all this information is provided
  234. | so if you write your own exception handlers you have enough information
  235. | to deal with the problem).
  236. | Then checks to see if the corresponding exception is trap-enabled, 
  237. | in which case it pushes the address of _fpCCR and traps through 
  238. | trap FPTRAP (15 for the moment).
  239.  
  240. FPTRAP = 15
  241.  
  242. $_exception_handler:
  243.     lea    SYM (_fpCCR),a0
  244.     movew    d7,a0@(EBITS)    | set __exception_bits
  245.     orw    d7,a0@(STICK)    | and __sticky_bits
  246.     movew    d6,a0@(FORMT)    | and __format
  247.     movew    d5,a0@(LASTO)    | and __last_operation
  248.  
  249. | Now put the operands in place:
  250.     cmpw    IMM (SINGLE_FLOAT),d6
  251.     beq    1f
  252.     movel    a6@(8),a0@(OPER1)
  253.     movel    a6@(12),a0@(OPER1+4)
  254.     movel    a6@(16),a0@(OPER2)
  255.     movel    a6@(20),a0@(OPER2+4)
  256.     bra    2f
  257. 1:    movel    a6@(8),a0@(OPER1)
  258.     movel    a6@(12),a0@(OPER2)
  259. 2:
  260. | And check whether the exception is trap-enabled:
  261.     andw    a0@(TRAPE),d7    | is exception trap-enabled?
  262.     beq    1f        | no, exit
  263.     pea    SYM (_fpCCR)    | yes, push address of _fpCCR
  264.     trap    IMM (FPTRAP)    | and trap
  265. 1:    moveml    sp@+,d2-d7    | restore data registers
  266.     unlk    a6        | and return
  267.     rts
  268. #endif /* L_floatex */
  269.  
  270. #ifdef  L_mulsi3
  271.     .text
  272.     .proc
  273.     .globl    SYM (__mulsi3)
  274. SYM (__mulsi3):
  275.     movew    sp@(4), d0    /* x0 -> d0 */
  276.     muluw    sp@(10), d0    /* x0*y1 */
  277.     movew    sp@(6), d1    /* x1 -> d1 */
  278.     muluw    sp@(8), d1    /* x1*y0 */
  279.     addw    d1, d0
  280.     swap    d0
  281.     clrw    d0
  282.     movew    sp@(6), d1    /* x1 -> d1 */
  283.     muluw    sp@(10), d1    /* x1*y1 */
  284.     addl    d1, d0
  285.  
  286.     rts
  287. #endif /* L_mulsi3 */
  288.  
  289. #ifdef  L_udivsi3
  290.     .text
  291.     .proc
  292.     .globl    SYM (__udivsi3)
  293. SYM (__udivsi3):
  294.     movel    d2, sp@-
  295.     movel    sp@(12), d1    /* d1 = divisor */
  296.     movel    sp@(8), d0    /* d0 = dividend */
  297.  
  298.     cmpl    IMM (0x10000), d1 /* divisor >= 2 ^ 16 ?   */
  299.     jcc    L3        /* then try next algorithm */
  300.     movel    d0, d2
  301.     clrw    d2
  302.     swap    d2
  303.     divu    d1, d2          /* high quotient in lower word */
  304.     movew    d2, d0        /* save high quotient */
  305.     swap    d0
  306.     movew    sp@(10), d2    /* get low dividend + high rest */
  307.     divu    d1, d2        /* low quotient */
  308.     movew    d2, d0
  309.     jra    L6
  310.  
  311. L3:    movel    d1, d2        /* use d2 as divisor backup */
  312. L4:    lsrl    IMM (1), d1    /* shift divisor */
  313.     lsrl    IMM (1), d0    /* shift dividend */
  314.     cmpl    IMM (0x10000), d1 /* still divisor >= 2 ^ 16 ?  */
  315.     jcc    L4
  316.     divu    d1, d0        /* now we have 16 bit divisor */
  317.     andl    IMM (0xffff), d0 /* mask out divisor, ignore remainder */
  318.  
  319. /* Multiply the 16 bit tentative quotient with the 32 bit divisor.  Because of
  320.    the operand ranges, this might give a 33 bit product.  If this product is
  321.    greater than the dividend, the tentative quotient was too large. */
  322.     movel    d2, d1
  323.     mulu    d0, d1        /* low part, 32 bits */
  324.     swap    d2
  325.     mulu    d0, d2        /* high part, at most 17 bits */
  326.     swap    d2        /* align high part with low part */
  327.     btst    IMM (0), d2    /* high part 17 bits? */
  328.     jne    L5        /* if 17 bits, quotient was too large */
  329.     addl    d2, d1        /* add parts */
  330.     jcs    L5        /* if sum is 33 bits, quotient was too large */
  331.     cmpl    sp@(8), d1    /* compare the sum with the dividend */
  332.     jls    L6        /* if sum > dividend, quotient was too large */
  333. L5:    subql    IMM (1), d0    /* adjust quotient */
  334.  
  335. L6:    movel    sp@+, d2
  336.     rts
  337. #endif /* L_udivsi3 */
  338.  
  339. #ifdef  L_divsi3
  340.     .text
  341.     .proc
  342.     .globl    SYM (__divsi3)
  343. SYM (__divsi3):
  344.     movel    d2, sp@-
  345.  
  346.     moveb    IMM (1), d2    /* sign of result stored in d2 (=1 or =-1) */
  347.     movel    sp@(12), d1    /* d1 = divisor */
  348.     jpl    L1
  349.     negl    d1
  350.     negb    d2        /* change sign because divisor <0  */
  351. L1:    movel    sp@(8), d0    /* d0 = dividend */
  352.     jpl    L2
  353.     negl    d0
  354.     negb    d2
  355.  
  356. L2:    movel    d1, sp@-
  357.     movel    d0, sp@-
  358.     jbsr    SYM (__udivsi3)    /* divide abs(dividend) by abs(divisor) */
  359.     addql    IMM (8), sp
  360.  
  361.     tstb    d2
  362.     jpl    L3
  363.     negl    d0
  364.  
  365. L3:    movel    sp@+, d2
  366.     rts
  367. #endif /* L_divsi3 */
  368.  
  369. #ifdef  L_umodsi3
  370.     .text
  371.     .proc
  372.     .globl    SYM (__umodsi3)
  373. SYM (__umodsi3):
  374.     movel    sp@(8), d1    /* d1 = divisor */
  375.     movel    sp@(4), d0    /* d0 = dividend */
  376.     movel    d1, sp@-
  377.     movel    d0, sp@-
  378.     jbsr    SYM (__udivsi3)
  379.     addql    IMM (8), sp
  380.     movel    sp@(8), d1    /* d1 = divisor */
  381.     movel    d1, sp@-
  382.     movel    d0, sp@-
  383.     jbsr    SYM (__mulsi3)    /* d0 = (a/b)*b */
  384.     addql    IMM (8), sp
  385.     movel    sp@(4), d1    /* d1 = dividend */
  386.     subl    d0, d1        /* d1 = a - (a/b)*b */
  387.     movel    d1, d0
  388.     rts
  389. #endif /* L_umodsi3 */
  390.  
  391. #ifdef  L_modsi3
  392.     .text
  393.     .proc
  394.     .globl    SYM (__modsi3)
  395. SYM (__modsi3):
  396.     movel    sp@(8), d1    /* d1 = divisor */
  397.     movel    sp@(4), d0    /* d0 = dividend */
  398.     movel    d1, sp@-
  399.     movel    d0, sp@-
  400.     jbsr    SYM (__divsi3)
  401.     addql    IMM (8), sp
  402.     movel    sp@(8), d1    /* d1 = divisor */
  403.     movel    d1, sp@-
  404.     movel    d0, sp@-
  405.     jbsr    SYM (__mulsi3)    /* d0 = (a/b)*b */
  406.     addql    IMM (8), sp
  407.     movel    sp@(4), d1    /* d1 = dividend */
  408.     subl    d0, d1        /* d1 = a - (a/b)*b */
  409.     movel    d1, d0
  410.     rts
  411. #endif /* L_modsi3 */
  412.  
  413.  
  414. #ifdef  L_double
  415.  
  416.     .globl    SYM (_fpCCR)
  417.     .globl  $_exception_handler
  418.  
  419. QUIET_NaN      = 0xffffffff
  420.  
  421. D_MAX_EXP      = 0x07ff
  422. D_BIAS         = 1022
  423. DBL_MAX_EXP    = D_MAX_EXP - D_BIAS
  424. DBL_MIN_EXP    = 1 - D_BIAS
  425. DBL_MANT_DIG   = 53
  426.  
  427. INEXACT_RESULT         = 0x0001
  428. UNDERFLOW         = 0x0002
  429. OVERFLOW         = 0x0004
  430. DIVIDE_BY_ZERO         = 0x0008
  431. INVALID_OPERATION     = 0x0010
  432.  
  433. DOUBLE_FLOAT = 2
  434.  
  435. NOOP         = 0
  436. ADD          = 1
  437. MULTIPLY     = 2
  438. DIVIDE       = 3
  439. NEGATE       = 4
  440. COMPARE      = 5
  441. EXTENDSFDF   = 6
  442. TRUNCDFSF    = 7
  443.  
  444. UNKNOWN           = -1
  445. ROUND_TO_NEAREST  = 0 | round result to nearest representable value
  446. ROUND_TO_ZERO     = 1 | round result towards zero
  447. ROUND_TO_PLUS     = 2 | round result towards plus infinity
  448. ROUND_TO_MINUS    = 3 | round result towards minus infinity
  449.  
  450. | Entry points:
  451.  
  452.     .globl SYM (__adddf3)
  453.     .globl SYM (__subdf3)
  454.     .globl SYM (__muldf3)
  455.     .globl SYM (__divdf3)
  456.     .globl SYM (__negdf2)
  457.     .globl SYM (__cmpdf2)
  458.  
  459.     .text
  460.     .even
  461.  
  462. | These are common routines to return and signal exceptions.    
  463.  
  464. Ld$den:
  465. | Return and signal a denormalized number
  466.     orl    d7,d0
  467.     movew    IMM (UNDERFLOW),d7
  468.     orw    IMM (INEXACT_RESULT),d7
  469.     movew    IMM (DOUBLE_FLOAT),d6
  470.     jmp    $_exception_handler
  471.  
  472. Ld$infty:
  473. Ld$overflow:
  474. | Return a properly signed INFINITY and set the exception flags 
  475.     movel    IMM (0x7ff00000),d0
  476.     movel    IMM (0),d1
  477.     orl    d7,d0
  478.     movew    IMM (OVERFLOW),d7
  479.     orw    IMM (INEXACT_RESULT),d7
  480.     movew    IMM (DOUBLE_FLOAT),d6
  481.     jmp    $_exception_handler
  482.  
  483. Ld$underflow:
  484. | Return 0 and set the exception flags 
  485.     movel    IMM (0),d0
  486.     movel    d0,d1
  487.     movew    IMM (UNDERFLOW),d7
  488.     orw    IMM (INEXACT_RESULT),d7
  489.     movew    IMM (DOUBLE_FLOAT),d6
  490.     jmp    $_exception_handler
  491.  
  492. Ld$inop:
  493. | Return a quiet NaN and set the exception flags
  494.     movel    IMM (QUIET_NaN),d0
  495.     movel    d0,d1
  496.     movew    IMM (INVALID_OPERATION),d7
  497.     orw    IMM (INEXACT_RESULT),d7
  498.     movew    IMM (DOUBLE_FLOAT),d6
  499.     jmp    $_exception_handler
  500.  
  501. Ld$div$0:
  502. | Return a properly signed INFINITY and set the exception flags
  503.     movel    IMM (0x7ff00000),d0
  504.     movel    IMM (0),d1
  505.     orl    d7,d0
  506.     movew    IMM (DIVIDE_BY_ZERO),d7
  507.     orw    IMM (INEXACT_RESULT),d7
  508.     movew    IMM (DOUBLE_FLOAT),d6
  509.     jmp    $_exception_handler
  510.  
  511. |=============================================================================
  512. |=============================================================================
  513. |                         double precision routines
  514. |=============================================================================
  515. |=============================================================================
  516.  
  517. | A double precision floating point number (double) has the format:
  518. |
  519. | struct _double {
  520. |  unsigned int sign      : 1;  /* sign bit */ 
  521. |  unsigned int exponent  : 11; /* exponent, shifted by 126 */
  522. |  unsigned int fraction  : 52; /* fraction */
  523. | } double;
  524. | Thus sizeof(double) = 8 (64 bits). 
  525. |
  526. | All the routines are callable from C programs, and return the result 
  527. | in the register pair d0-d1. They also preserve all registers except 
  528. | d0-d1 and a0-a1.
  529.  
  530. |=============================================================================
  531. |                              __subdf3
  532. |=============================================================================
  533.  
  534. | double __subdf3(double, double);
  535. SYM (__subdf3):
  536.     bchg    IMM (31),sp@(12) | change sign of second operand
  537.                 | and fall through, so we always add
  538. |=============================================================================
  539. |                              __adddf3
  540. |=============================================================================
  541.  
  542. | double __adddf3(double, double);
  543. SYM (__adddf3):
  544.     link    a6,IMM (0)    | everything will be done in registers
  545.     moveml    d2-d7,sp@-    | save all data registers and a2 (but d0-d1)
  546.     movel    a6@(8),d0    | get first operand
  547.     movel    a6@(12),d1    | 
  548.     movel    a6@(16),d2    | get second operand
  549.     movel    a6@(20),d3    | 
  550.  
  551.     movel    d0,d7        | get d0's sign bit in d7 '
  552.     addl    d1,d1        | check and clear sign bit of a, and gain one
  553.     addxl    d0,d0        | bit of extra precision
  554.     beq    Ladddf$b    | if zero return second operand
  555.  
  556.     movel    d2,d6        | save sign in d6 
  557.     addl    d3,d3        | get rid of sign bit and gain one bit of
  558.     addxl    d2,d2        | extra precision
  559.     beq    Ladddf$a    | if zero return first operand
  560.  
  561.     andl    IMM (0x80000000),d7 | isolate a's sign bit '
  562.         swap    d6        | and also b's sign bit '
  563.     andw    IMM (0x8000),d6    |
  564.     orw    d6,d7        | and combine them into d7, so that a's sign '
  565.                 | bit is in the high word and b's is in the '
  566.                 | low word, so d6 is free to be used
  567.     movel    d7,a0        | now save d7 into a0, so d7 is free to
  568.                         | be used also
  569.  
  570. | Get the exponents and check for denormalized and/or infinity.
  571.  
  572.     movel    IMM (0x001fffff),d6 | mask for the fraction
  573.     movel    IMM (0x00200000),d7 | mask to put hidden bit back
  574.  
  575.     movel    d0,d4        | 
  576.     andl    d6,d0        | get fraction in d0
  577.     notl    d6        | make d6 into mask for the exponent
  578.     andl    d6,d4        | get exponent in d4
  579.     beq    Ladddf$a$den    | branch if a is denormalized
  580.     cmpl    d6,d4        | check for INFINITY or NaN
  581.     beq    Ladddf$nf       | 
  582.     orl    d7,d0        | and put hidden bit back
  583. Ladddf$1:
  584.     swap    d4        | shift right exponent so that it starts
  585.     lsrw    IMM (5),d4    | in bit 0 and not bit 20
  586. | Now we have a's exponent in d4 and fraction in d0-d1 '
  587.     movel    d2,d5        | save b to get exponent
  588.     andl    d6,d5        | get exponent in d5
  589.     beq    Ladddf$b$den    | branch if b is denormalized
  590.     cmpl    d6,d5        | check for INFINITY or NaN
  591.     beq    Ladddf$nf
  592.     notl    d6        | make d6 into mask for the fraction again
  593.     andl    d6,d2        | and get fraction in d2
  594.     orl    d7,d2        | and put hidden bit back
  595. Ladddf$2:
  596.     swap    d5        | shift right exponent so that it starts
  597.     lsrw    IMM (5),d5    | in bit 0 and not bit 20
  598.  
  599. | Now we have b's exponent in d5 and fraction in d2-d3. '
  600.  
  601. | The situation now is as follows: the signs are combined in a0, the 
  602. | numbers are in d0-d1 (a) and d2-d3 (b), and the exponents in d4 (a)
  603. | and d5 (b). To do the rounding correctly we need to keep all the
  604. | bits until the end, so we need to use d0-d1-d2-d3 for the first number
  605. | and d4-d5-d6-d7 for the second. To do this we store (temporarily) the
  606. | exponents in a2-a3.
  607.  
  608.     moveml    a2-a3,sp@-    | save the address registers
  609.  
  610.     movel    d4,a2        | save the exponents
  611.     movel    d5,a3        | 
  612.  
  613.     movel    IMM (0),d7    | and move the numbers around
  614.     movel    d7,d6        |
  615.     movel    d3,d5        |
  616.     movel    d2,d4        |
  617.     movel    d7,d3        |
  618.     movel    d7,d2        |
  619.  
  620. | Here we shift the numbers until the exponents are the same, and put 
  621. | the largest exponent in a2.
  622.     exg    d4,a2        | get exponents back
  623.     exg    d5,a3        |
  624.     cmpw    d4,d5        | compare the exponents
  625.     beq    Ladddf$3    | if equal don't shift '
  626.     bhi    9f        | branch if second exponent is higher
  627.  
  628. | Here we have a's exponent larger than b's, so we have to shift b. We do 
  629. | this by using as counter d2:
  630. 1:    movew    d4,d2        | move largest exponent to d2
  631.     subw    d5,d2        | and subtract second exponent
  632.     exg    d4,a2        | get back the longs we saved
  633.     exg    d5,a3        |
  634. | if difference is too large we don't shift (actually, we can just exit) '
  635.     cmpw    IMM (DBL_MANT_DIG+2),d2
  636.     bge    Ladddf$b$small
  637.     cmpw    IMM (32),d2    | if difference >= 32, shift by longs
  638.     bge    5f
  639. 2:    cmpw    IMM (16),d2    | if difference >= 16, shift by words    
  640.     bge    6f
  641.     bra    3f        | enter dbra loop
  642.  
  643. 4:    lsrl    IMM (1),d4
  644.     roxrl    IMM (1),d5
  645.     roxrl    IMM (1),d6
  646.     roxrl    IMM (1),d7
  647. 3:    dbra    d2,4b
  648.     movel    IMM (0),d2
  649.     movel    d2,d3    
  650.     bra    Ladddf$4
  651. 5:
  652.     movel    d6,d7
  653.     movel    d5,d6
  654.     movel    d4,d5
  655.     movel    IMM (0),d4
  656.     subw    IMM (32),d2
  657.     bra    2b
  658. 6:
  659.     movew    d6,d7
  660.     swap    d7
  661.     movew    d5,d6
  662.     swap    d6
  663.     movew    d4,d5
  664.     swap    d5
  665.     movew    IMM (0),d4
  666.     swap    d4
  667.     subw    IMM (16),d2
  668.     bra    3b
  669.     
  670. 9:    exg    d4,d5
  671.     movew    d4,d6
  672.     subw    d5,d6        | keep d5 (largest exponent) in d4
  673.     exg    d4,a2
  674.     exg    d5,a3
  675. | if difference is too large we don't shift (actually, we can just exit) '
  676.     cmpw    IMM (DBL_MANT_DIG+2),d6
  677.     bge    Ladddf$a$small
  678.     cmpw    IMM (32),d6    | if difference >= 32, shift by longs
  679.     bge    5f
  680. 2:    cmpw    IMM (16),d6    | if difference >= 16, shift by words    
  681.     bge    6f
  682.     bra    3f        | enter dbra loop
  683.  
  684. 4:    lsrl    IMM (1),d0
  685.     roxrl    IMM (1),d1
  686.     roxrl    IMM (1),d2
  687.     roxrl    IMM (1),d3
  688. 3:    dbra    d6,4b
  689.     movel    IMM (0),d7
  690.     movel    d7,d6
  691.     bra    Ladddf$4
  692. 5:
  693.     movel    d2,d3
  694.     movel    d1,d2
  695.     movel    d0,d1
  696.     movel    IMM (0),d0
  697.     subw    IMM (32),d6
  698.     bra    2b
  699. 6:
  700.     movew    d2,d3
  701.     swap    d3
  702.     movew    d1,d2
  703.     swap    d2
  704.     movew    d0,d1
  705.     swap    d1
  706.     movew    IMM (0),d0
  707.     swap    d0
  708.     subw    IMM (16),d6
  709.     bra    3b
  710. Ladddf$3:
  711.     exg    d4,a2    
  712.     exg    d5,a3
  713. Ladddf$4:    
  714. | Now we have the numbers in d0--d3 and d4--d7, the exponent in a2, and
  715. | the signs in a4.
  716.  
  717. | Here we have to decide whether to add or subtract the numbers:
  718.     exg    d7,a0        | get the signs 
  719.     exg    d6,a3        | a3 is free to be used
  720.     movel    d7,d6        |
  721.     movew    IMM (0),d7    | get a's sign in d7 '
  722.     swap    d6              |
  723.     movew    IMM (0),d6    | and b's sign in d6 '
  724.     eorl    d7,d6        | compare the signs
  725.     bmi    Lsubdf$0    | if the signs are different we have 
  726.                 | to subtract
  727.     exg    d7,a0        | else we add the numbers
  728.     exg    d6,a3        |
  729.     addl    d7,d3        |
  730.     addxl    d6,d2        |
  731.     addxl    d5,d1        | 
  732.     addxl    d4,d0           |
  733.  
  734.     movel    a2,d4        | return exponent to d4
  735.     movel    a0,d7        | 
  736.     andl    IMM (0x80000000),d7 | d7 now has the sign
  737.  
  738.     moveml    sp@+,a2-a3    
  739.  
  740. | Before rounding normalize so bit #DBL_MANT_DIG is set (we will consider
  741. | the case of denormalized numbers in the rounding routine itself).
  742. | As in the addition (not in the subtraction!) we could have set 
  743. | one more bit we check this:
  744.     btst    IMM (DBL_MANT_DIG+1),d0    
  745.     beq    1f
  746.     lsrl    IMM (1),d0
  747.     roxrl    IMM (1),d1
  748.     roxrl    IMM (1),d2
  749.     roxrl    IMM (1),d3
  750.     addw    IMM (1),d4
  751. 1:
  752.     lea    Ladddf$5,a0    | to return from rounding routine
  753.     lea    SYM (_fpCCR),a1    | check the rounding mode
  754.     movew    a1@(6),d6    | rounding mode in d6
  755.     beq    Lround$to$nearest
  756.     cmpw    IMM (ROUND_TO_PLUS),d6
  757.     bhi    Lround$to$minus
  758.     blt    Lround$to$zero
  759.     bra    Lround$to$plus
  760. Ladddf$5:
  761. | Put back the exponent and check for overflow
  762.     cmpw    IMM (0x7ff),d4    | is the exponent big?
  763.     bge    1f
  764.     bclr    IMM (DBL_MANT_DIG-1),d0
  765.     lslw    IMM (4),d4    | put exponent back into position
  766.     swap    d0        | 
  767.     orw    d4,d0        |
  768.     swap    d0        |
  769.     bra    Ladddf$ret
  770. 1:
  771.     movew    IMM (ADD),d5
  772.     bra    Ld$overflow
  773.  
  774. Lsubdf$0:
  775. | Here we do the subtraction.
  776.     exg    d7,a0        | put sign back in a0
  777.     exg    d6,a3        |
  778.     subl    d7,d3        |
  779.     subxl    d6,d2        |
  780.     subxl    d5,d1        |
  781.     subxl    d4,d0        |
  782.     beq    Ladddf$ret$1    | if zero just exit
  783.     bpl    1f        | if positive skip the following
  784.     exg    d7,a0        |
  785.     bchg    IMM (31),d7    | change sign bit in d7
  786.     exg    d7,a0        |
  787.     negl    d3        |
  788.     negxl    d2        |
  789.     negxl    d1              | and negate result
  790.     negxl    d0              |
  791. 1:    
  792.     movel    a2,d4        | return exponent to d4
  793.     movel    a0,d7
  794.     andl    IMM (0x80000000),d7 | isolate sign bit
  795.     moveml    sp@+,a2-a3    |
  796.  
  797. | Before rounding normalize so bit #DBL_MANT_DIG is set (we will consider
  798. | the case of denormalized numbers in the rounding routine itself).
  799. | As in the addition (not in the subtraction!) we could have set 
  800. | one more bit we check this:
  801.     btst    IMM (DBL_MANT_DIG+1),d0    
  802.     beq    1f
  803.     lsrl    IMM (1),d0
  804.     roxrl    IMM (1),d1
  805.     roxrl    IMM (1),d2
  806.     roxrl    IMM (1),d3
  807.     addw    IMM (1),d4
  808. 1:
  809.     lea    Lsubdf$1,a0    | to return from rounding routine
  810.     lea    SYM (_fpCCR),a1    | check the rounding mode
  811.     movew    a1@(6),d6    | rounding mode in d6
  812.     beq    Lround$to$nearest
  813.     cmpw    IMM (ROUND_TO_PLUS),d6
  814.     bhi    Lround$to$minus
  815.     blt    Lround$to$zero
  816.     bra    Lround$to$plus
  817. Lsubdf$1:
  818. | Put back the exponent and sign (we don't have overflow). '
  819.     bclr    IMM (DBL_MANT_DIG-1),d0    
  820.     lslw    IMM (4),d4    | put exponent back into position
  821.     swap    d0        | 
  822.     orw    d4,d0        |
  823.     swap    d0        |
  824.     bra    Ladddf$ret
  825.  
  826. | If one of the numbers was too small (difference of exponents >= 
  827. | DBL_MANT_DIG+1) we return the other (and now we don't have to '
  828. | check for finiteness or zero).
  829. Ladddf$a$small:
  830.     moveml    sp@+,a2-a3    
  831.     movel    a6@(16),d0
  832.     movel    a6@(20),d1
  833.     lea    SYM (_fpCCR),a0
  834.     movew    IMM (0),a0@
  835.     moveml    sp@+,d2-d7    | restore data registers
  836.     unlk    a6        | and return
  837.     rts
  838.  
  839. Ladddf$b$small:
  840.     moveml    sp@+,a2-a3    
  841.     movel    a6@(8),d0
  842.     movel    a6@(12),d1
  843.     lea    SYM (_fpCCR),a0
  844.     movew    IMM (0),a0@
  845.     moveml    sp@+,d2-d7    | restore data registers
  846.     unlk    a6        | and return
  847.     rts
  848.  
  849. Ladddf$a$den:
  850.     movel    d7,d4        | d7 contains 0x00200000
  851.     bra    Ladddf$1
  852.  
  853. Ladddf$b$den:
  854.     movel    d7,d5           | d7 contains 0x00200000
  855.     notl    d6
  856.     bra    Ladddf$2
  857.  
  858. Ladddf$b:
  859. | Return b (if a is zero)
  860.     movel    d2,d0
  861.     movel    d3,d1
  862.     bra    1f
  863. Ladddf$a:
  864.     movel    a6@(8),d0
  865.     movel    a6@(12),d1
  866. 1:
  867.     movew    IMM (ADD),d5
  868. | Check for NaN and +/-INFINITY.
  869.     movel    d0,d7                 |
  870.     andl    IMM (0x80000000),d7    |
  871.     bclr    IMM (31),d0        |
  872.     cmpl    IMM (0x7ff00000),d0    |
  873.     bge    2f            |
  874.     movel    d0,d0               | check for zero, since we don't  '
  875.     bne    Ladddf$ret        | want to return -0 by mistake
  876.     bclr    IMM (31),d7        |
  877.     bra    Ladddf$ret        |
  878. 2:
  879.     andl    IMM (0x000fffff),d0    | check for NaN (nonzero fraction)
  880.     orl    d1,d0            |
  881.     bne    Ld$inop             |
  882.     bra    Ld$infty        |
  883.     
  884. Ladddf$ret$1:
  885.     moveml    sp@+,a2-a3    | restore regs and exit
  886.  
  887. Ladddf$ret:
  888. | Normal exit.
  889.     lea    SYM (_fpCCR),a0
  890.     movew    IMM (0),a0@
  891.     orl    d7,d0        | put sign bit back
  892.     moveml    sp@+,d2-d7
  893.     unlk    a6
  894.     rts
  895.  
  896. Ladddf$ret$den:
  897. | Return a denormalized number.
  898.     lsrl    IMM (1),d0    | shift right once more
  899.     roxrl    IMM (1),d1    |
  900.     bra    Ladddf$ret
  901.  
  902. Ladddf$nf:
  903.     movew    IMM (ADD),d5
  904. | This could be faster but it is not worth the effort, since it is not
  905. | executed very often. We sacrifice speed for clarity here.
  906.     movel    a6@(8),d0    | get the numbers back (remember that we
  907.     movel    a6@(12),d1    | did some processing already)
  908.     movel    a6@(16),d2    | 
  909.     movel    a6@(20),d3    | 
  910.     movel    IMM (0x7ff00000),d4 | useful constant (INFINITY)
  911.     movel    d0,d7        | save sign bits
  912.     movel    d2,d6        | 
  913.     bclr    IMM (31),d0    | clear sign bits
  914.     bclr    IMM (31),d2    | 
  915. | We know that one of them is either NaN of +/-INFINITY
  916. | Check for NaN (if either one is NaN return NaN)
  917.     cmpl    d4,d0        | check first a (d0)
  918.     bhi    Ld$inop        | if d0 > 0x7ff00000 or equal and
  919.     bne    2f
  920.     tstl    d1        | d1 > 0, a is NaN
  921.     bne    Ld$inop        | 
  922. 2:    cmpl    d4,d2        | check now b (d1)
  923.     bhi    Ld$inop        | 
  924.     bne    3f
  925.     tstl    d3        | 
  926.     bne    Ld$inop        | 
  927. 3:
  928. | Now comes the check for +/-INFINITY. We know that both are (maybe not
  929. | finite) numbers, but we have to check if both are infinite whether we
  930. | are adding or subtracting them.
  931.     eorl    d7,d6        | to check sign bits
  932.     bmi    1f
  933.     andl    IMM (0x80000000),d7 | get (common) sign bit
  934.     bra    Ld$infty
  935. 1:
  936. | We know one (or both) are infinite, so we test for equality between the
  937. | two numbers (if they are equal they have to be infinite both, so we
  938. | return NaN).
  939.     cmpl    d2,d0        | are both infinite?
  940.     bne    1f        | if d0 <> d2 they are not equal
  941.     cmpl    d3,d1        | if d0 == d2 test d3 and d1
  942.     beq    Ld$inop        | if equal return NaN
  943. 1:    
  944.     andl    IMM (0x80000000),d7 | get a's sign bit '
  945.     cmpl    d4,d0        | test now for infinity
  946.     beq    Ld$infty    | if a is INFINITY return with this sign
  947.     bchg    IMM (31),d7    | else we know b is INFINITY and has
  948.     bra    Ld$infty    | the opposite sign
  949.  
  950. |=============================================================================
  951. |                              __muldf3
  952. |=============================================================================
  953.  
  954. | double __muldf3(double, double);
  955. SYM (__muldf3):
  956.     link    a6,IMM (0)
  957.     moveml    d2-d7,sp@-
  958.     movel    a6@(8),d0        | get a into d0-d1
  959.     movel    a6@(12),d1        | 
  960.     movel    a6@(16),d2        | and b into d2-d3
  961.     movel    a6@(20),d3        |
  962.     movel    d0,d7            | d7 will hold the sign of the product
  963.     eorl    d2,d7            |
  964.     andl    IMM (0x80000000),d7    |
  965.     movel    d7,a0            | save sign bit into a0 
  966.     movel    IMM (0x7ff00000),d7    | useful constant (+INFINITY)
  967.     movel    d7,d6            | another (mask for fraction)
  968.     notl    d6            |
  969.     bclr    IMM (31),d0        | get rid of a's sign bit '
  970.     movel    d0,d4            | 
  971.     orl    d1,d4            | 
  972.     beq    Lmuldf$a$0        | branch if a is zero
  973.     movel    d0,d4            |
  974.     bclr    IMM (31),d2        | get rid of b's sign bit '
  975.     movel    d2,d5            |
  976.     orl    d3,d5            | 
  977.     beq    Lmuldf$b$0        | branch if b is zero
  978.     movel    d2,d5            | 
  979.     cmpl    d7,d0            | is a big?
  980.     bhi    Lmuldf$inop        | if a is NaN return NaN
  981.     beq    Lmuldf$a$nf        | we still have to check d1 and b ...
  982.     cmpl    d7,d2            | now compare b with INFINITY
  983.     bhi    Lmuldf$inop        | is b NaN?
  984.     beq    Lmuldf$b$nf         | we still have to check d3 ...
  985. | Here we have both numbers finite and nonzero (and with no sign bit).
  986. | Now we get the exponents into d4 and d5.
  987.     andl    d7,d4            | isolate exponent in d4
  988.     beq    Lmuldf$a$den        | if exponent zero, have denormalized
  989.     andl    d6,d0            | isolate fraction
  990.     orl    IMM (0x00100000),d0    | and put hidden bit back
  991.     swap    d4            | I like exponents in the first byte
  992.     lsrw    IMM (4),d4        | 
  993. Lmuldf$1:            
  994.     andl    d7,d5            |
  995.     beq    Lmuldf$b$den        |
  996.     andl    d6,d2            |
  997.     orl    IMM (0x00100000),d2    | and put hidden bit back
  998.     swap    d5            |
  999.     lsrw    IMM (4),d5        |
  1000. Lmuldf$2:                |
  1001.     addw    d5,d4            | add exponents
  1002.     subw    IMM (D_BIAS+1),d4    | and subtract bias (plus one)
  1003.  
  1004. | We are now ready to do the multiplication. The situation is as follows:
  1005. | both a and b have bit 52 ( bit 20 of d0 and d2) set (even if they were 
  1006. | denormalized to start with!), which means that in the product bit 104 
  1007. | (which will correspond to bit 8 of the fourth long) is set.
  1008.  
  1009. | Here we have to do the product.
  1010. | To do it we have to juggle the registers back and forth, as there are not
  1011. | enough to keep everything in them. So we use the address registers to keep
  1012. | some intermediate data.
  1013.  
  1014.     moveml    a2-a3,sp@-    | save a2 and a3 for temporary use
  1015.     movel    IMM (0),a2    | a2 is a null register
  1016.     movel    d4,a3        | and a3 will preserve the exponent
  1017.  
  1018. | First, shift d2-d3 so bit 20 becomes bit 31:
  1019.     rorl    IMM (5),d2    | rotate d2 5 places right
  1020.     swap    d2        | and swap it
  1021.     rorl    IMM (5),d3    | do the same thing with d3
  1022.     swap    d3        |
  1023.     movew    d3,d6        | get the rightmost 11 bits of d3
  1024.     andw    IMM (0x07ff),d6    |
  1025.     orw    d6,d2        | and put them into d2
  1026.     andw    IMM (0xf800),d3    | clear those bits in d3
  1027.  
  1028.     movel    d2,d6        | move b into d6-d7
  1029.     movel    d3,d7           | move a into d4-d5
  1030.     movel    d0,d4           | and clear d0-d1-d2-d3 (to put result)
  1031.     movel    d1,d5           |
  1032.     movel    IMM (0),d3    |
  1033.     movel    d3,d2           |
  1034.     movel    d3,d1           |
  1035.     movel    d3,d0            |
  1036.  
  1037. | We use a1 as counter:    
  1038.     movel    IMM (DBL_MANT_DIG-1),a1        
  1039.     exg    d7,a1
  1040.  
  1041. 1:    exg    d7,a1        | put counter back in a1
  1042.     addl    d3,d3        | shift sum once left
  1043.     addxl    d2,d2           |
  1044.     addxl    d1,d1           |
  1045.     addxl    d0,d0           |
  1046.     addl    d7,d7        |
  1047.     addxl    d6,d6        |
  1048.     bcc    2f        | if bit clear skip the following
  1049.     exg    d7,a2        |
  1050.     addl    d5,d3        | else add a to the sum
  1051.     addxl    d4,d2        |
  1052.     addxl    d7,d1        |
  1053.     addxl    d7,d0        |
  1054.     exg    d7,a2        | 
  1055. 2:    exg    d7,a1        | put counter in d7
  1056.     dbf    d7,1b        | decrement and branch
  1057.  
  1058.     movel    a3,d4        | restore exponent
  1059.     moveml    sp@+,a2-a3
  1060.  
  1061. | Now we have the product in d0-d1-d2-d3, with bit 8 of d0 set. The 
  1062. | first thing to do now is to normalize it so bit 8 becomes bit 
  1063. | DBL_MANT_DIG-32 (to do the rounding); later we will shift right.
  1064.     swap    d0
  1065.     swap    d1
  1066.     movew    d1,d0
  1067.     swap    d2
  1068.     movew    d2,d1
  1069.     swap    d3
  1070.     movew    d3,d2
  1071.     movew    IMM (0),d3
  1072.     lsrl    IMM (1),d0
  1073.     roxrl    IMM (1),d1
  1074.     roxrl    IMM (1),d2
  1075.     roxrl    IMM (1),d3
  1076.     lsrl    IMM (1),d0
  1077.     roxrl    IMM (1),d1
  1078.     roxrl    IMM (1),d2
  1079.     roxrl    IMM (1),d3
  1080.     lsrl    IMM (1),d0
  1081.     roxrl    IMM (1),d1
  1082.     roxrl    IMM (1),d2
  1083.     roxrl    IMM (1),d3
  1084.     
  1085. | Now round, check for over- and underflow, and exit.
  1086.     movel    a0,d7        | get sign bit back into d7
  1087.     movew    IMM (MULTIPLY),d5
  1088.  
  1089.     btst    IMM (DBL_MANT_DIG+1-32),d0
  1090.     beq    Lround$exit
  1091.     lsrl    IMM (1),d0
  1092.     roxrl    IMM (1),d1
  1093.     addw    IMM (1),d4
  1094.     bra    Lround$exit
  1095.  
  1096. Lmuldf$inop:
  1097.     movew    IMM (MULTIPLY),d5
  1098.     bra    Ld$inop
  1099.  
  1100. Lmuldf$b$nf:
  1101.     movew    IMM (MULTIPLY),d5
  1102.     movel    a0,d7        | get sign bit back into d7
  1103.     tstl    d3        | we know d2 == 0x7ff00000, so check d3
  1104.     bne    Ld$inop        | if d3 <> 0 b is NaN
  1105.     bra    Ld$overflow    | else we have overflow (since a is finite)
  1106.  
  1107. Lmuldf$a$nf:
  1108.     movew    IMM (MULTIPLY),d5
  1109.     movel    a0,d7        | get sign bit back into d7
  1110.     tstl    d1        | we know d0 == 0x7ff00000, so check d1
  1111.     bne    Ld$inop        | if d1 <> 0 a is NaN
  1112.     bra    Ld$overflow    | else signal overflow
  1113.  
  1114. | If either number is zero return zero, unless the other is +/-INFINITY or
  1115. | NaN, in which case we return NaN.
  1116. Lmuldf$b$0:
  1117.     movew    IMM (MULTIPLY),d5
  1118.     exg    d2,d0        | put b (==0) into d0-d1
  1119.     exg    d3,d1        | and a (with sign bit cleared) into d2-d3
  1120.     bra    1f
  1121. Lmuldf$a$0:
  1122.     movel    a6@(16),d2    | put b into d2-d3 again
  1123.     movel    a6@(20),d3    |
  1124.     bclr    IMM (31),d2    | clear sign bit
  1125. 1:    cmpl    IMM (0x7ff00000),d2 | check for non-finiteness
  1126.     bge    Ld$inop        | in case NaN or +/-INFINITY return NaN
  1127.     lea    SYM (_fpCCR),a0
  1128.     movew    IMM (0),a0@
  1129.     moveml    sp@+,d2-d7
  1130.     unlk    a6
  1131.     rts
  1132.  
  1133. | If a number is denormalized we put an exponent of 1 but do not put the 
  1134. | hidden bit back into the fraction; instead we shift left until bit 21
  1135. | (the hidden bit) is set, adjusting the exponent accordingly. We do this
  1136. | to ensure that the product of the fractions is close to 1.
  1137. Lmuldf$a$den:
  1138.     movel    IMM (1),d4
  1139.     andl    d6,d0
  1140. 1:    addl    d1,d1           | shift a left until bit 20 is set
  1141.     addxl    d0,d0        |
  1142.     subw    IMM (1),d4    | and adjust exponent
  1143.     btst    IMM (20),d0    |
  1144.     bne    Lmuldf$1        |
  1145.     bra    1b
  1146.  
  1147. Lmuldf$b$den:
  1148.     movel    IMM (1),d5
  1149.     andl    d6,d2
  1150. 1:    addl    d3,d3        | shift b left until bit 20 is set
  1151.     addxl    d2,d2        |
  1152.     subw    IMM (1),d5    | and adjust exponent
  1153.     btst    IMM (20),d2    |
  1154.     bne    Lmuldf$2    |
  1155.     bra    1b
  1156.  
  1157.  
  1158. |=============================================================================
  1159. |                              __divdf3
  1160. |=============================================================================
  1161.  
  1162. | double __divdf3(double, double);
  1163. SYM (__divdf3):
  1164.     link    a6,IMM (0)
  1165.     moveml    d2-d7,sp@-
  1166.     movel    a6@(8),d0    | get a into d0-d1
  1167.     movel    a6@(12),d1    | 
  1168.     movel    a6@(16),d2    | and b into d2-d3
  1169.     movel    a6@(20),d3    |
  1170.     movel    d0,d7        | d7 will hold the sign of the result
  1171.     eorl    d2,d7        |
  1172.     andl    IMM (0x80000000),d7
  1173.     movel    d7,a0        | save sign into a0
  1174.     movel    IMM (0x7ff00000),d7 | useful constant (+INFINITY)
  1175.     movel    d7,d6        | another (mask for fraction)
  1176.     notl    d6        |
  1177.     bclr    IMM (31),d0    | get rid of a's sign bit '
  1178.     movel    d0,d4        |
  1179.     orl    d1,d4        |
  1180.     beq    Ldivdf$a$0    | branch if a is zero
  1181.     movel    d0,d4        |
  1182.     bclr    IMM (31),d2    | get rid of b's sign bit '
  1183.     movel    d2,d5        |
  1184.     orl    d3,d5        |
  1185.     beq    Ldivdf$b$0    | branch if b is zero
  1186.     movel    d2,d5
  1187.     cmpl    d7,d0        | is a big?
  1188.     bhi    Ldivdf$inop    | if a is NaN return NaN
  1189.     beq    Ldivdf$a$nf    | if d0 == 0x7ff00000 we check d1
  1190.     cmpl    d7,d2        | now compare b with INFINITY 
  1191.     bhi    Ldivdf$inop    | if b is NaN return NaN
  1192.     beq    Ldivdf$b$nf    | if d2 == 0x7ff00000 we check d3
  1193. | Here we have both numbers finite and nonzero (and with no sign bit).
  1194. | Now we get the exponents into d4 and d5 and normalize the numbers to
  1195. | ensure that the ratio of the fractions is around 1. We do this by
  1196. | making sure that both numbers have bit #DBL_MANT_DIG-32-1 (hidden bit)
  1197. | set, even if they were denormalized to start with.
  1198. | Thus, the result will satisfy: 2 > result > 1/2.
  1199.     andl    d7,d4        | and isolate exponent in d4
  1200.     beq    Ldivdf$a$den    | if exponent is zero we have a denormalized
  1201.     andl    d6,d0        | and isolate fraction
  1202.     orl    IMM (0x00100000),d0 | and put hidden bit back
  1203.     swap    d4        | I like exponents in the first byte
  1204.     lsrw    IMM (4),d4    | 
  1205. Ldivdf$1:            | 
  1206.     andl    d7,d5        |
  1207.     beq    Ldivdf$b$den    |
  1208.     andl    d6,d2        |
  1209.     orl    IMM (0x00100000),d2
  1210.     swap    d5        |
  1211.     lsrw    IMM (4),d5    |
  1212. Ldivdf$2:            |
  1213.     subw    d5,d4        | subtract exponents
  1214.     addw    IMM (D_BIAS),d4    | and add bias
  1215.  
  1216. | We are now ready to do the division. We have prepared things in such a way
  1217. | that the ratio of the fractions will be less than 2 but greater than 1/2.
  1218. | At this point the registers in use are:
  1219. | d0-d1    hold a (first operand, bit DBL_MANT_DIG-32=0, bit 
  1220. | DBL_MANT_DIG-1-32=1)
  1221. | d2-d3    hold b (second operand, bit DBL_MANT_DIG-32=1)
  1222. | d4    holds the difference of the exponents, corrected by the bias
  1223. | a0    holds the sign of the ratio
  1224.  
  1225. | To do the rounding correctly we need to keep information about the
  1226. | nonsignificant bits. One way to do this would be to do the division
  1227. | using four registers; another is to use two registers (as originally
  1228. | I did), but use a sticky bit to preserve information about the 
  1229. | fractional part. Note that we can keep that info in a1, which is not
  1230. | used.
  1231.     movel    IMM (0),d6    | d6-d7 will hold the result
  1232.     movel    d6,d7        | 
  1233.     movel    IMM (0),a1    | and a1 will hold the sticky bit
  1234.  
  1235.     movel    IMM (DBL_MANT_DIG-32+1),d5    
  1236.     
  1237. 1:    cmpl    d0,d2        | is a < b?
  1238.     bhi    3f        | if b > a skip the following
  1239.     beq    4f        | if d0==d2 check d1 and d3
  1240. 2:    subl    d3,d1        | 
  1241.     subxl    d2,d0        | a <-- a - b
  1242.     bset    d5,d6        | set the corresponding bit in d6
  1243. 3:    addl    d1,d1        | shift a by 1
  1244.     addxl    d0,d0        |
  1245.     dbra    d5,1b        | and branch back
  1246.     bra    5f            
  1247. 4:    cmpl    d1,d3        | here d0==d2, so check d1 and d3
  1248.     bhi    3b        | if d1 > d2 skip the subtraction
  1249.     bra    2b        | else go do it
  1250. 5:
  1251. | Here we have to start setting the bits in the second long.
  1252.     movel    IMM (31),d5    | again d5 is counter
  1253.  
  1254. 1:    cmpl    d0,d2        | is a < b?
  1255.     bhi    3f        | if b > a skip the following
  1256.     beq    4f        | if d0==d2 check d1 and d3
  1257. 2:    subl    d3,d1        | 
  1258.     subxl    d2,d0        | a <-- a - b
  1259.     bset    d5,d7        | set the corresponding bit in d7
  1260. 3:    addl    d1,d1        | shift a by 1
  1261.     addxl    d0,d0        |
  1262.     dbra    d5,1b        | and branch back
  1263.     bra    5f            
  1264. 4:    cmpl    d1,d3        | here d0==d2, so check d1 and d3
  1265.     bhi    3b        | if d1 > d2 skip the subtraction
  1266.     bra    2b        | else go do it
  1267. 5:
  1268. | Now go ahead checking until we hit a one, which we store in d2.
  1269.     movel    IMM (DBL_MANT_DIG),d5
  1270. 1:    cmpl    d2,d0        | is a < b?
  1271.     bhi    4f        | if b < a, exit
  1272.     beq    3f        | if d0==d2 check d1 and d3
  1273. 2:    addl    d1,d1        | shift a by 1
  1274.     addxl    d0,d0        |
  1275.     dbra    d5,1b        | and branch back
  1276.     movel    IMM (0),d2    | here no sticky bit was found
  1277.     movel    d2,d3
  1278.     bra    5f            
  1279. 3:    cmpl    d1,d3        | here d0==d2, so check d1 and d3
  1280.     bhi    2b        | if d1 > d2 go back
  1281. 4:
  1282. | Here put the sticky bit in d2-d3 (in the position which actually corresponds
  1283. | to it; if you don't do this the algorithm loses in some cases). '
  1284.     movel    IMM (0),d2
  1285.     movel    d2,d3
  1286.     subw    IMM (DBL_MANT_DIG),d5
  1287.     addw    IMM (63),d5
  1288.     cmpw    IMM (31),d5
  1289.     bhi    2f
  1290. 1:    bset    d5,d3
  1291.     bra    5f
  1292.     subw    IMM (32),d5
  1293. 2:    bset    d5,d2
  1294. 5:
  1295. | Finally we are finished! Move the longs in the address registers to
  1296. | their final destination:
  1297.     movel    d6,d0
  1298.     movel    d7,d1
  1299.     movel    IMM (0),d3
  1300.  
  1301. | Here we have finished the division, with the result in d0-d1-d2-d3, with
  1302. | 2^21 <= d6 < 2^23. Thus bit 23 is not set, but bit 22 could be set.
  1303. | If it is not, then definitely bit 21 is set. Normalize so bit 22 is
  1304. | not set:
  1305.     btst    IMM (DBL_MANT_DIG-32+1),d0
  1306.     beq    1f
  1307.     lsrl    IMM (1),d0
  1308.     roxrl    IMM (1),d1
  1309.     roxrl    IMM (1),d2
  1310.     roxrl    IMM (1),d3
  1311.     addw    IMM (1),d4
  1312. 1:
  1313. | Now round, check for over- and underflow, and exit.
  1314.     movel    a0,d7        | restore sign bit to d7
  1315.     movew    IMM (DIVIDE),d5
  1316.     bra    Lround$exit
  1317.  
  1318. Ldivdf$inop:
  1319.     movew    IMM (DIVIDE),d5
  1320.     bra    Ld$inop
  1321.  
  1322. Ldivdf$a$0:
  1323. | If a is zero check to see whether b is zero also. In that case return
  1324. | NaN; then check if b is NaN, and return NaN also in that case. Else
  1325. | return zero.
  1326.     movew    IMM (DIVIDE),d5
  1327.     bclr    IMM (31),d2    |
  1328.     movel    d2,d4        | 
  1329.     orl    d3,d4        | 
  1330.     beq    Ld$inop        | if b is also zero return NaN
  1331.     cmpl    IMM (0x7ff00000),d2 | check for NaN
  1332.     bhi    Ld$inop        | 
  1333.     blt    1f        |
  1334.     tstl    d3        |
  1335.     bne    Ld$inop        |
  1336. 1:    movel    IMM (0),d0    | else return zero
  1337.     movel    d0,d1        | 
  1338.     lea    SYM (_fpCCR),a0    | clear exception flags
  1339.     movew    IMM (0),a0@    |
  1340.     moveml    sp@+,d2-d7    | 
  1341.     unlk    a6        | 
  1342.     rts            |     
  1343.  
  1344. Ldivdf$b$0:
  1345.     movew    IMM (DIVIDE),d5
  1346. | If we got here a is not zero. Check if a is NaN; in that case return NaN,
  1347. | else return +/-INFINITY. Remember that a is in d0 with the sign bit 
  1348. | cleared already.
  1349.     movel    a0,d7        | put a's sign bit back in d7 '
  1350.     cmpl    IMM (0x7ff00000),d0 | compare d0 with INFINITY
  1351.     bhi    Ld$inop        | if larger it is NaN
  1352.     tstl    d1        | 
  1353.     bne    Ld$inop        | 
  1354.     bra    Ld$div$0    | else signal DIVIDE_BY_ZERO
  1355.  
  1356. Ldivdf$b$nf:
  1357.     movew    IMM (DIVIDE),d5
  1358. | If d2 == 0x7ff00000 we have to check d3.
  1359.     tstl    d3        |
  1360.     bne    Ld$inop        | if d3 <> 0, b is NaN
  1361.     bra    Ld$underflow    | else b is +/-INFINITY, so signal underflow
  1362.  
  1363. Ldivdf$a$nf:
  1364.     movew    IMM (DIVIDE),d5
  1365. | If d0 == 0x7ff00000 we have to check d1.
  1366.     tstl    d1        |
  1367.     bne    Ld$inop        | if d1 <> 0, a is NaN
  1368. | If a is INFINITY we have to check b
  1369.     cmpl    d7,d2        | compare b with INFINITY 
  1370.     bge    Ld$inop        | if b is NaN or INFINITY return NaN
  1371.     tstl    d3        |
  1372.     bne    Ld$inop        | 
  1373.     bra    Ld$overflow    | else return overflow
  1374.  
  1375. | If a number is denormalized we put an exponent of 1 but do not put the 
  1376. | bit back into the fraction.
  1377. Ldivdf$a$den:
  1378.     movel    IMM (1),d4
  1379.     andl    d6,d0
  1380. 1:    addl    d1,d1        | shift a left until bit 20 is set
  1381.     addxl    d0,d0
  1382.     subw    IMM (1),d4    | and adjust exponent
  1383.     btst    IMM (DBL_MANT_DIG-32-1),d0
  1384.     bne    Ldivdf$1
  1385.     bra    1b
  1386.  
  1387. Ldivdf$b$den:
  1388.     movel    IMM (1),d5
  1389.     andl    d6,d2
  1390. 1:    addl    d3,d3        | shift b left until bit 20 is set
  1391.     addxl    d2,d2
  1392.     subw    IMM (1),d5    | and adjust exponent
  1393.     btst    IMM (DBL_MANT_DIG-32-1),d2
  1394.     bne    Ldivdf$2
  1395.     bra    1b
  1396.  
  1397. Lround$exit:
  1398. | This is a common exit point for __muldf3 and __divdf3. When they enter
  1399. | this point the sign of the result is in d7, the result in d0-d1, normalized
  1400. | so that 2^21 <= d0 < 2^22, and the exponent is in the lower byte of d4.
  1401.  
  1402. | First check for underlow in the exponent:
  1403.     cmpw    IMM (-DBL_MANT_DIG-1),d4        
  1404.     blt    Ld$underflow    
  1405. | It could happen that the exponent is less than 1, in which case the 
  1406. | number is denormalized. In this case we shift right and adjust the 
  1407. | exponent until it becomes 1 or the fraction is zero (in the latter case 
  1408. | we signal underflow and return zero).
  1409.     movel    d7,a0        |
  1410.     movel    IMM (0),d6    | use d6-d7 to collect bits flushed right
  1411.     movel    d6,d7        | use d6-d7 to collect bits flushed right
  1412.     cmpw    IMM (1),d4    | if the exponent is less than 1 we 
  1413.     bge    2f        | have to shift right (denormalize)
  1414. 1:    addw    IMM (1),d4    | adjust the exponent
  1415.     lsrl    IMM (1),d0    | shift right once 
  1416.     roxrl    IMM (1),d1    |
  1417.     roxrl    IMM (1),d2    |
  1418.     roxrl    IMM (1),d3    |
  1419.     roxrl    IMM (1),d6    | 
  1420.     roxrl    IMM (1),d7    |
  1421.     cmpw    IMM (1),d4    | is the exponent 1 already?
  1422.     beq    2f        | if not loop back
  1423.     bra    1b              |
  1424.     bra    Ld$underflow    | safety check, shouldn't execute '
  1425. 2:    orl    d6,d2        | this is a trick so we don't lose  '
  1426.     orl    d7,d3        | the bits which were flushed right
  1427.     movel    a0,d7        | get back sign bit into d7
  1428. | Now call the rounding routine (which takes care of denormalized numbers):
  1429.     lea    Lround$0,a0    | to return from rounding routine
  1430.     lea    SYM (_fpCCR),a1    | check the rounding mode
  1431.     movew    a1@(6),d6    | rounding mode in d6
  1432.     beq    Lround$to$nearest
  1433.     cmpw    IMM (ROUND_TO_PLUS),d6
  1434.     bhi    Lround$to$minus
  1435.     blt    Lround$to$zero
  1436.     bra    Lround$to$plus
  1437. Lround$0:
  1438. | Here we have a correctly rounded result (either normalized or denormalized).
  1439.  
  1440. | Here we should have either a normalized number or a denormalized one, and
  1441. | the exponent is necessarily larger or equal to 1 (so we don't have to  '
  1442. | check again for underflow!). We have to check for overflow or for a 
  1443. | denormalized number (which also signals underflow).
  1444. | Check for overflow (i.e., exponent >= 0x7ff).
  1445.     cmpw    IMM (0x07ff),d4
  1446.     bge    Ld$overflow
  1447. | Now check for a denormalized number (exponent==0):
  1448.     movew    d4,d4
  1449.     beq    Ld$den
  1450. 1:
  1451. | Put back the exponents and sign and return.
  1452.     lslw    IMM (4),d4    | exponent back to fourth byte
  1453.     bclr    IMM (DBL_MANT_DIG-32-1),d0
  1454.     swap    d0        | and put back exponent
  1455.     orw    d4,d0        | 
  1456.     swap    d0        |
  1457.     orl    d7,d0        | and sign also
  1458.  
  1459.     lea    SYM (_fpCCR),a0
  1460.     movew    IMM (0),a0@
  1461.     moveml    sp@+,d2-d7
  1462.     unlk    a6
  1463.     rts
  1464.  
  1465. |=============================================================================
  1466. |                              __negdf2
  1467. |=============================================================================
  1468.  
  1469. | double __negdf2(double, double);
  1470. SYM (__negdf2):
  1471.     link    a6,IMM (0)
  1472.     moveml    d2-d7,sp@-
  1473.     movew    IMM (NEGATE),d5
  1474.     movel    a6@(8),d0    | get number to negate in d0-d1
  1475.     movel    a6@(12),d1    |
  1476.     bchg    IMM (31),d0    | negate
  1477.     movel    d0,d2        | make a positive copy (for the tests)
  1478.     bclr    IMM (31),d2    |
  1479.     movel    d2,d4        | check for zero
  1480.     orl    d1,d4        |
  1481.     beq    2f        | if zero (either sign) return +zero
  1482.     cmpl    IMM (0x7ff00000),d2 | compare to +INFINITY
  1483.     blt    1f        | if finite, return
  1484.     bhi    Ld$inop        | if larger (fraction not zero) is NaN
  1485.     tstl    d1        | if d2 == 0x7ff00000 check d1
  1486.     bne    Ld$inop        |
  1487.     movel    d0,d7        | else get sign and return INFINITY
  1488.     andl    IMM (0x80000000),d7
  1489.     bra    Ld$infty        
  1490. 1:    lea    SYM (_fpCCR),a0
  1491.     movew    IMM (0),a0@
  1492.     moveml    sp@+,d2-d7
  1493.     unlk    a6
  1494.     rts
  1495. 2:    bclr    IMM (31),d0
  1496.     bra    1b
  1497.  
  1498. |=============================================================================
  1499. |                              __cmpdf2
  1500. |=============================================================================
  1501.  
  1502. GREATER =  1
  1503. LESS    = -1
  1504. EQUAL   =  0
  1505.  
  1506. | int __cmpdf2(double, double);
  1507. SYM (__cmpdf2):
  1508.     link    a6,IMM (0)
  1509.     moveml    d2-d7,sp@-     | save registers
  1510.     movew    IMM (COMPARE),d5
  1511.     movel    a6@(8),d0    | get first operand
  1512.     movel    a6@(12),d1    |
  1513.     movel    a6@(16),d2    | get second operand
  1514.     movel    a6@(20),d3    |
  1515. | First check if a and/or b are (+/-) zero and in that case clear
  1516. | the sign bit.
  1517.     movel    d0,d6        | copy signs into d6 (a) and d7(b)
  1518.     bclr    IMM (31),d0    | and clear signs in d0 and d2
  1519.     movel    d2,d7        |
  1520.     bclr    IMM (31),d2    |
  1521.     cmpl    IMM (0x7fff0000),d0 | check for a == NaN
  1522.     bhi    Ld$inop        | if d0 > 0x7ff00000, a is NaN
  1523.     beq    Lcmpdf$a$nf    | if equal can be INFINITY, so check d1
  1524.     movel    d0,d4        | copy into d4 to test for zero
  1525.     orl    d1,d4        |
  1526.     beq    Lcmpdf$a$0    |
  1527. Lcmpdf$0:
  1528.     cmpl    IMM (0x7fff0000),d2 | check for b == NaN
  1529.     bhi    Ld$inop        | if d2 > 0x7ff00000, b is NaN
  1530.     beq    Lcmpdf$b$nf    | if equal can be INFINITY, so check d3
  1531.     movel    d2,d4        |
  1532.     orl    d3,d4        |
  1533.     beq    Lcmpdf$b$0    |
  1534. Lcmpdf$1:
  1535. | Check the signs
  1536.     eorl    d6,d7
  1537.     bpl    1f
  1538. | If the signs are not equal check if a >= 0
  1539.     tstl    d6
  1540.     bpl    Lcmpdf$a$gt$b    | if (a >= 0 && b < 0) => a > b
  1541.     bmi    Lcmpdf$b$gt$a    | if (a < 0 && b >= 0) => a < b
  1542. 1:
  1543. | If the signs are equal check for < 0
  1544.     tstl    d6
  1545.     bpl    1f
  1546. | If both are negative exchange them
  1547.     exg    d0,d2
  1548.     exg    d1,d3
  1549. 1:
  1550. | Now that they are positive we just compare them as longs (does this also
  1551. | work for denormalized numbers?).
  1552.     cmpl    d0,d2
  1553.     bhi    Lcmpdf$b$gt$a    | |b| > |a|
  1554.     bne    Lcmpdf$a$gt$b    | |b| < |a|
  1555. | If we got here d0 == d2, so we compare d1 and d3.
  1556.     cmpl    d1,d3
  1557.     bhi    Lcmpdf$b$gt$a    | |b| > |a|
  1558.     bne    Lcmpdf$a$gt$b    | |b| < |a|
  1559. | If we got here a == b.
  1560.     movel    IMM (EQUAL),d0
  1561.     moveml    sp@+,d2-d7     | put back the registers
  1562.     unlk    a6
  1563.     rts
  1564. Lcmpdf$a$gt$b:
  1565.     movel    IMM (GREATER),d0
  1566.     moveml    sp@+,d2-d7     | put back the registers
  1567.     unlk    a6
  1568.     rts
  1569. Lcmpdf$b$gt$a:
  1570.     movel    IMM (LESS),d0
  1571.     moveml    sp@+,d2-d7     | put back the registers
  1572.     unlk    a6
  1573.     rts
  1574.  
  1575. Lcmpdf$a$0:    
  1576.     bclr    IMM (31),d6
  1577.     bra    Lcmpdf$0
  1578. Lcmpdf$b$0:
  1579.     bclr    IMM (31),d7
  1580.     bra    Lcmpdf$1
  1581.  
  1582. Lcmpdf$a$nf:
  1583.     tstl    d1
  1584.     bne    Ld$inop
  1585.     bra    Lcmpdf$0
  1586.  
  1587. Lcmpdf$b$nf:
  1588.     tstl    d3
  1589.     bne    Ld$inop
  1590.     bra    Lcmpdf$1
  1591.  
  1592. |=============================================================================
  1593. |                           rounding routines
  1594. |=============================================================================
  1595.  
  1596. | The rounding routines expect the number to be normalized in registers
  1597. | d0-d1-d2-d3, with the exponent in register d4. They assume that the 
  1598. | exponent is larger or equal to 1. They return a properly normalized number
  1599. | if possible, and a denormalized number otherwise. The exponent is returned
  1600. | in d4.
  1601.  
  1602. Lround$to$nearest:
  1603. | We now normalize as suggested by D. Knuth ("Seminumerical Algorithms"):
  1604. | Here we assume that the exponent is not too small (this should be checked
  1605. | before entering the rounding routine), but the number could be denormalized.
  1606.  
  1607. | Check for denormalized numbers:
  1608. 1:    btst    IMM (DBL_MANT_DIG-32),d0
  1609.     bne    2f        | if set the number is normalized
  1610. | Normalize shifting left until bit #DBL_MANT_DIG-32 is set or the exponent 
  1611. | is one (remember that a denormalized number corresponds to an 
  1612. | exponent of -D_BIAS+1).
  1613.     cmpw    IMM (1),d4    | remember that the exponent is at least one
  1614.      beq    2f        | an exponent of one means denormalized
  1615.     addl    d3,d3        | else shift and adjust the exponent
  1616.     addxl    d2,d2        |
  1617.     addxl    d1,d1        |
  1618.     addxl    d0,d0        |
  1619.     dbra    d4,1b        |
  1620. 2:
  1621. | Now round: we do it as follows: after the shifting we can write the
  1622. | fraction part as f + delta, where 1 < f < 2^25, and 0 <= delta <= 2.
  1623. | If delta < 1, do nothing. If delta > 1, add 1 to f. 
  1624. | If delta == 1, we make sure the rounded number will be even (odd?) 
  1625. | (after shifting).
  1626.     btst    IMM (0),d1    | is delta < 1?
  1627.     beq    2f        | if so, do not do anything
  1628.     orl    d2,d3        | is delta == 1?
  1629.     bne    1f        | if so round to even
  1630.     movel    d1,d3        | 
  1631.     andl    IMM (2),d3    | bit 1 is the last significant bit
  1632.     movel    IMM (0),d2    |
  1633.     addl    d3,d1        |
  1634.     addxl    d2,d0        |
  1635.     bra    2f        | 
  1636. 1:    movel    IMM (1),d3    | else add 1 
  1637.     movel    IMM (0),d2    |
  1638.     addl    d3,d1        |
  1639.     addxl    d2,d0
  1640. | Shift right once (because we used bit #DBL_MANT_DIG-32!).
  1641. 2:    lsrl    IMM (1),d0
  1642.     roxrl    IMM (1),d1        
  1643.  
  1644. | Now check again bit #DBL_MANT_DIG-32 (rounding could have produced a
  1645. | 'fraction overflow' ...).
  1646.     btst    IMM (DBL_MANT_DIG-32),d0    
  1647.     beq    1f
  1648.     lsrl    IMM (1),d0
  1649.     roxrl    IMM (1),d1
  1650.     addw    IMM (1),d4
  1651. 1:
  1652. | If bit #DBL_MANT_DIG-32-1 is clear we have a denormalized number, so we 
  1653. | have to put the exponent to zero and return a denormalized number.
  1654.     btst    IMM (DBL_MANT_DIG-32-1),d0
  1655.     beq    1f
  1656.     jmp    a0@
  1657. 1:    movel    IMM (0),d4
  1658.     jmp    a0@
  1659.  
  1660. Lround$to$zero:
  1661. Lround$to$plus:
  1662. Lround$to$minus:
  1663.     jmp    a0@
  1664. #endif /* L_double */
  1665.  
  1666. #ifdef  L_float
  1667.  
  1668.     .globl    SYM (_fpCCR)
  1669.     .globl  $_exception_handler
  1670.  
  1671. QUIET_NaN    = 0xffffffff
  1672. SIGNL_NaN    = 0x7f800001
  1673. INFINITY     = 0x7f800000
  1674.  
  1675. F_MAX_EXP      = 0xff
  1676. F_BIAS         = 126
  1677. FLT_MAX_EXP    = F_MAX_EXP - F_BIAS
  1678. FLT_MIN_EXP    = 1 - F_BIAS
  1679. FLT_MANT_DIG   = 24
  1680.  
  1681. INEXACT_RESULT         = 0x0001
  1682. UNDERFLOW         = 0x0002
  1683. OVERFLOW         = 0x0004
  1684. DIVIDE_BY_ZERO         = 0x0008
  1685. INVALID_OPERATION     = 0x0010
  1686.  
  1687. SINGLE_FLOAT = 1
  1688.  
  1689. NOOP         = 0
  1690. ADD          = 1
  1691. MULTIPLY     = 2
  1692. DIVIDE       = 3
  1693. NEGATE       = 4
  1694. COMPARE      = 5
  1695. EXTENDSFDF   = 6
  1696. TRUNCDFSF    = 7
  1697.  
  1698. UNKNOWN           = -1
  1699. ROUND_TO_NEAREST  = 0 | round result to nearest representable value
  1700. ROUND_TO_ZERO     = 1 | round result towards zero
  1701. ROUND_TO_PLUS     = 2 | round result towards plus infinity
  1702. ROUND_TO_MINUS    = 3 | round result towards minus infinity
  1703.  
  1704. | Entry points:
  1705.  
  1706.     .globl SYM (__addsf3)
  1707.     .globl SYM (__subsf3)
  1708.     .globl SYM (__mulsf3)
  1709.     .globl SYM (__divsf3)
  1710.     .globl SYM (__negsf2)
  1711.     .globl SYM (__cmpsf2)
  1712.  
  1713. | These are common routines to return and signal exceptions.    
  1714.  
  1715.     .text
  1716.     .even
  1717.  
  1718. Lf$den:
  1719. | Return and signal a denormalized number
  1720.     orl    d7,d0
  1721.     movew    IMM (UNDERFLOW),d7
  1722.     orw    IMM (INEXACT_RESULT),d7
  1723.     movew    IMM (SINGLE_FLOAT),d6
  1724.     jmp    $_exception_handler
  1725.  
  1726. Lf$infty:
  1727. Lf$overflow:
  1728. | Return a properly signed INFINITY and set the exception flags 
  1729.     movel    IMM (INFINITY),d0
  1730.     orl    d7,d0
  1731.     movew    IMM (OVERFLOW),d7
  1732.     orw    IMM (INEXACT_RESULT),d7
  1733.     movew    IMM (SINGLE_FLOAT),d6
  1734.     jmp    $_exception_handler
  1735.  
  1736. Lf$underflow:
  1737. | Return 0 and set the exception flags 
  1738.     movel    IMM (0),d0
  1739.     movew    IMM (UNDERFLOW),d7
  1740.     orw    IMM (INEXACT_RESULT),d7
  1741.     movew    IMM (SINGLE_FLOAT),d6
  1742.     jmp    $_exception_handler
  1743.  
  1744. Lf$inop:
  1745. | Return a quiet NaN and set the exception flags
  1746.     movel    IMM (QUIET_NaN),d0
  1747.     movew    IMM (INVALID_OPERATION),d7
  1748.     orw    IMM (INEXACT_RESULT),d7
  1749.     movew    IMM (SINGLE_FLOAT),d6
  1750.     jmp    $_exception_handler
  1751.  
  1752. Lf$div$0:
  1753. | Return a properly signed INFINITY and set the exception flags
  1754.     movel    IMM (INFINITY),d0
  1755.     orl    d7,d0
  1756.     movew    IMM (DIVIDE_BY_ZERO),d7
  1757.     orw    IMM (INEXACT_RESULT),d7
  1758.     movew    IMM (SINGLE_FLOAT),d6
  1759.     jmp    $_exception_handler
  1760.  
  1761. |=============================================================================
  1762. |=============================================================================
  1763. |                         single precision routines
  1764. |=============================================================================
  1765. |=============================================================================
  1766.  
  1767. | A single precision floating point number (float) has the format:
  1768. |
  1769. | struct _float {
  1770. |  unsigned int sign      : 1;  /* sign bit */ 
  1771. |  unsigned int exponent  : 8;  /* exponent, shifted by 126 */
  1772. |  unsigned int fraction  : 23; /* fraction */
  1773. | } float;
  1774. | Thus sizeof(float) = 4 (32 bits). 
  1775. |
  1776. | All the routines are callable from C programs, and return the result 
  1777. | in the single register d0. They also preserve all registers except 
  1778. | d0-d1 and a0-a1.
  1779.  
  1780. |=============================================================================
  1781. |                              __subsf3
  1782. |=============================================================================
  1783.  
  1784. | float __subsf3(float, float);
  1785. SYM (__subsf3):
  1786.     bchg    IMM (31),sp@(8)    | change sign of second operand
  1787.                 | and fall through
  1788. |=============================================================================
  1789. |                              __addsf3
  1790. |=============================================================================
  1791.  
  1792. | float __addsf3(float, float);
  1793. SYM (__addsf3):
  1794.     link    a6,IMM (0)    | everything will be done in registers
  1795.     moveml    d2-d7,sp@-    | save all data registers but d0-d1
  1796.     movel    a6@(8),d0    | get first operand
  1797.     movel    a6@(12),d1    | get second operand
  1798.     movel    d0,d6        | get d0's sign bit '
  1799.     addl    d0,d0        | check and clear sign bit of a
  1800.     beq    Laddsf$b    | if zero return second operand
  1801.     movel    d1,d7        | save b's sign bit '
  1802.     addl    d1,d1        | get rid of sign bit
  1803.     beq    Laddsf$a    | if zero return first operand
  1804.  
  1805.     movel    d6,a0        | save signs in address registers
  1806.     movel    d7,a1        | so we can use d6 and d7
  1807.  
  1808. | Get the exponents and check for denormalized and/or infinity.
  1809.  
  1810.     movel    IMM (0x00ffffff),d4    | mask to get fraction
  1811.     movel    IMM (0x01000000),d5    | mask to put hidden bit back
  1812.  
  1813.     movel    d0,d6        | save a to get exponent
  1814.     andl    d4,d0        | get fraction in d0
  1815.     notl     d4        | make d4 into a mask for the exponent
  1816.     andl    d4,d6        | get exponent in d6
  1817.     beq    Laddsf$a$den    | branch if a is denormalized
  1818.     cmpl    d4,d6        | check for INFINITY or NaN
  1819.     beq    Laddsf$nf
  1820.     swap    d6        | put exponent into first word
  1821.     orl    d5,d0        | and put hidden bit back
  1822. Laddsf$1:
  1823. | Now we have a's exponent in d6 (second byte) and the mantissa in d0. '
  1824.     movel    d1,d7        | get exponent in d7
  1825.     andl    d4,d7        | 
  1826.     beq    Laddsf$b$den    | branch if b is denormalized
  1827.     cmpl    d4,d7        | check for INFINITY or NaN
  1828.     beq    Laddsf$nf
  1829.     swap    d7        | put exponent into first word
  1830.     notl     d4        | make d4 into a mask for the fraction
  1831.     andl    d4,d1        | get fraction in d1
  1832.     orl    d5,d1        | and put hidden bit back
  1833. Laddsf$2:
  1834. | Now we have b's exponent in d7 (second byte) and the mantissa in d1. '
  1835.  
  1836. | Note that the hidden bit corresponds to bit #FLT_MANT_DIG-1, and we 
  1837. | shifted right once, so bit #FLT_MANT_DIG is set (so we have one extra
  1838. | bit).
  1839.  
  1840.     movel    d1,d2        | move b to d2, since we want to use
  1841.                 | two registers to do the sum
  1842.     movel    IMM (0),d1    | and clear the new ones
  1843.     movel    d1,d3        |
  1844.  
  1845. | Here we shift the numbers in registers d0 and d1 so the exponents are the
  1846. | same, and put the largest exponent in d6. Note that we are using two
  1847. | registers for each number (see the discussion by D. Knuth in "Seminumerical 
  1848. | Algorithms").
  1849.     cmpw    d6,d7        | compare exponents
  1850.     beq    Laddsf$3    | if equal don't shift '
  1851.     bhi    5f        | branch if second exponent largest
  1852. 1:
  1853.     subl    d6,d7        | keep the largest exponent
  1854.     negl    d7
  1855.     lsrw    IMM (8),d7    | put difference in lower byte
  1856. | if difference is too large we don't shift (actually, we can just exit) '
  1857.     cmpw    IMM (FLT_MANT_DIG+2),d7        
  1858.     bge    Laddsf$b$small
  1859.     cmpw    IMM (16),d7    | if difference >= 16 swap
  1860.     bge    4f
  1861. 2:
  1862.     subw    IMM (1),d7
  1863. 3:    lsrl    IMM (1),d2    | shift right second operand
  1864.     roxrl    IMM (1),d3
  1865.     dbra    d7,3b
  1866.     bra    Laddsf$3
  1867. 4:
  1868.     movew    d2,d3
  1869.     swap    d3
  1870.     movew    d3,d2
  1871.     swap    d2
  1872.     subw    IMM (16),d7
  1873.     bne    2b        | if still more bits, go back to normal case
  1874.     bra    Laddsf$3
  1875. 5:
  1876.     exg    d6,d7        | exchange the exponents
  1877.     subl    d6,d7        | keep the largest exponent
  1878.     negl    d7        |
  1879.     lsrw    IMM (8),d7    | put difference in lower byte
  1880. | if difference is too large we don't shift (and exit!) '
  1881.     cmpw    IMM (FLT_MANT_DIG+2),d7        
  1882.     bge    Laddsf$a$small
  1883.     cmpw    IMM (16),d7    | if difference >= 16 swap
  1884.     bge    8f
  1885. 6:
  1886.     subw    IMM (1),d7
  1887. 7:    lsrl    IMM (1),d0    | shift right first operand
  1888.     roxrl    IMM (1),d1
  1889.     dbra    d7,7b
  1890.     bra    Laddsf$3
  1891. 8:
  1892.     movew    d0,d1
  1893.     swap    d1
  1894.     movew    d1,d0
  1895.     swap    d0
  1896.     subw    IMM (16),d7
  1897.     bne    6b        | if still more bits, go back to normal case
  1898.                 | otherwise we fall through
  1899.  
  1900. | Now we have a in d0-d1, b in d2-d3, and the largest exponent in d6 (the
  1901. | signs are stored in a0 and a1).
  1902.  
  1903. Laddsf$3:
  1904. | Here we have to decide whether to add or subtract the numbers
  1905.     exg    d6,a0        | get signs back
  1906.     exg    d7,a1        | and save the exponents
  1907.     eorl    d6,d7        | combine sign bits
  1908.     bmi    Lsubsf$0    | if negative a and b have opposite 
  1909.                 | sign so we actually subtract the
  1910.                 | numbers
  1911.  
  1912. | Here we have both positive or both negative
  1913.     exg    d6,a0        | now we have the exponent in d6
  1914.     movel    a0,d7        | and sign in d7
  1915.     andl    IMM (0x80000000),d7
  1916. | Here we do the addition.
  1917.     addl    d3,d1
  1918.     addxl    d2,d0
  1919. | Note: now we have d2, d3, d4 and d5 to play with! 
  1920.  
  1921. | Put the exponent, in the first byte, in d2, to use the "standard" rounding
  1922. | routines:
  1923.     movel    d6,d2
  1924.     lsrw    IMM (8),d2
  1925.  
  1926. | Before rounding normalize so bit #FLT_MANT_DIG is set (we will consider
  1927. | the case of denormalized numbers in the rounding routine itself).
  1928. | As in the addition (not in the subtraction!) we could have set 
  1929. | one more bit we check this:
  1930.     btst    IMM (FLT_MANT_DIG+1),d0    
  1931.     beq    1f
  1932.     lsrl    IMM (1),d0
  1933.     roxrl    IMM (1),d1
  1934.     addl    IMM (1),d2
  1935. 1:
  1936.     lea    Laddsf$4,a0    | to return from rounding routine
  1937.     lea    SYM (_fpCCR),a1    | check the rounding mode
  1938.     movew    a1@(6),d6    | rounding mode in d6
  1939.     beq    Lround$to$nearest
  1940.     cmpw    IMM (ROUND_TO_PLUS),d6
  1941.     bhi    Lround$to$minus
  1942.     blt    Lround$to$zero
  1943.     bra    Lround$to$plus
  1944. Laddsf$4:
  1945. | Put back the exponent, but check for overflow.
  1946.     cmpw    IMM (0xff),d2
  1947.     bhi    1f
  1948.     bclr    IMM (FLT_MANT_DIG-1),d0
  1949.     lslw    IMM (7),d2
  1950.     swap    d2
  1951.     orl    d2,d0
  1952.     bra    Laddsf$ret
  1953. 1:
  1954.     movew    IMM (ADD),d5
  1955.     bra    Lf$overflow
  1956.  
  1957. Lsubsf$0:
  1958. | We are here if a > 0 and b < 0 (sign bits cleared).
  1959. | Here we do the subtraction.
  1960.     movel    d6,d7        | put sign in d7
  1961.     andl    IMM (0x80000000),d7
  1962.  
  1963.     subl    d3,d1        | result in d0-d1
  1964.     subxl    d2,d0        |
  1965.     beq    Laddsf$ret    | if zero just exit
  1966.     bpl    1f        | if positive skip the following
  1967.     bchg    IMM (31),d7    | change sign bit in d7
  1968.     negl    d1
  1969.     negxl    d0
  1970. 1:
  1971.     exg    d2,a0        | now we have the exponent in d2
  1972.     lsrw    IMM (8),d2    | put it in the first byte
  1973.  
  1974. | Now d0-d1 is positive and the sign bit is in d7.
  1975.  
  1976. | Note that we do not have to normalize, since in the subtraction bit
  1977. | #FLT_MANT_DIG+1 is never set, and denormalized numbers are handled by
  1978. | the rounding routines themselves.
  1979.     lea    Lsubsf$1,a0    | to return from rounding routine
  1980.     lea    SYM (_fpCCR),a1    | check the rounding mode
  1981.     movew    a1@(6),d6    | rounding mode in d6
  1982.     beq    Lround$to$nearest
  1983.     cmpw    IMM (ROUND_TO_PLUS),d6
  1984.     bhi    Lround$to$minus
  1985.     blt    Lround$to$zero
  1986.     bra    Lround$to$plus
  1987. Lsubsf$1:
  1988. | Put back the exponent (we can't have overflow!). '
  1989.     bclr    IMM (FLT_MANT_DIG-1),d0
  1990.     lslw    IMM (7),d2
  1991.     swap    d2
  1992.     orl    d2,d0
  1993.     bra    Laddsf$ret
  1994.  
  1995. | If one of the numbers was too small (difference of exponents >= 
  1996. | FLT_MANT_DIG+2) we return the other (and now we don't have to '
  1997. | check for finiteness or zero).
  1998. Laddsf$a$small:
  1999.     movel    a6@(12),d0
  2000.     lea    SYM (_fpCCR),a0
  2001.     movew    IMM (0),a0@
  2002.     moveml    sp@+,d2-d7    | restore data registers
  2003.     unlk    a6        | and return
  2004.     rts
  2005.  
  2006. Laddsf$b$small:
  2007.     movel    a6@(8),d0
  2008.     lea    SYM (_fpCCR),a0
  2009.     movew    IMM (0),a0@
  2010.     moveml    sp@+,d2-d7    | restore data registers
  2011.     unlk    a6        | and return
  2012.     rts
  2013.  
  2014. | If the numbers are denormalized remember to put exponent equal to 1.
  2015.  
  2016. Laddsf$a$den:
  2017.     movel    d5,d6        | d5 contains 0x01000000
  2018.     swap    d6
  2019.     bra    Laddsf$1
  2020.  
  2021. Laddsf$b$den:
  2022.     movel    d5,d7
  2023.     swap    d7
  2024.     notl     d4        | make d4 into a mask for the fraction
  2025.                 | (this was not executed after the jump)
  2026.     bra    Laddsf$2
  2027.  
  2028. | The rest is mainly code for the different results which can be 
  2029. | returned (checking always for +/-INFINITY and NaN).
  2030.  
  2031. Laddsf$b:
  2032. | Return b (if a is zero).
  2033.     movel    a6@(12),d0
  2034.     bra    1f
  2035. Laddsf$a:
  2036. | Return a (if b is zero).
  2037.     movel    a6@(8),d0
  2038. 1:
  2039.     movew    IMM (ADD),d5
  2040. | We have to check for NaN and +/-infty.
  2041.     movel    d0,d7
  2042.     andl    IMM (0x80000000),d7    | put sign in d7
  2043.     bclr    IMM (31),d0        | clear sign
  2044.     cmpl    IMM (INFINITY),d0    | check for infty or NaN
  2045.     bge    2f
  2046.     movel    d0,d0        | check for zero (we do this because we don't '
  2047.     bne    Laddsf$ret    | want to return -0 by mistake
  2048.     bclr    IMM (31),d7    | if zero be sure to clear sign
  2049.     bra    Laddsf$ret    | if everything OK just return
  2050. 2:
  2051. | The value to be returned is either +/-infty or NaN
  2052.     andl    IMM (0x007fffff),d0    | check for NaN
  2053.     bne    Lf$inop            | if mantissa not zero is NaN
  2054.     bra    Lf$infty
  2055.  
  2056. Laddsf$ret:
  2057. | Normal exit (a and b nonzero, result is not NaN nor +/-infty).
  2058. | We have to clear the exception flags (just the exception type).
  2059.     lea    SYM (_fpCCR),a0
  2060.     movew    IMM (0),a0@
  2061.     orl    d7,d0        | put sign bit
  2062.     moveml    sp@+,d2-d7    | restore data registers
  2063.     unlk    a6        | and return
  2064.     rts
  2065.  
  2066. Laddsf$ret$den:
  2067. | Return a denormalized number (for addition we don't signal underflow) '
  2068.     lsrl    IMM (1),d0    | remember to shift right back once
  2069.     bra    Laddsf$ret    | and return
  2070.  
  2071. | Note: when adding two floats of the same sign if either one is 
  2072. | NaN we return NaN without regard to whether the other is finite or 
  2073. | not. When subtracting them (i.e., when adding two numbers of 
  2074. | opposite signs) things are more complicated: if both are INFINITY 
  2075. | we return NaN, if only one is INFINITY and the other is NaN we return
  2076. | NaN, but if it is finite we return INFINITY with the corresponding sign.
  2077.  
  2078. Laddsf$nf:
  2079.     movew    IMM (ADD),d5
  2080. | This could be faster but it is not worth the effort, since it is not
  2081. | executed very often. We sacrifice speed for clarity here.
  2082.     movel    a6@(8),d0    | get the numbers back (remember that we
  2083.     movel    a6@(12),d1    | did some processing already)
  2084.     movel    IMM (INFINITY),d4 | useful constant (INFINITY)
  2085.     movel    d0,d2        | save sign bits
  2086.     movel    d1,d3
  2087.     bclr    IMM (31),d0    | clear sign bits
  2088.     bclr    IMM (31),d1
  2089. | We know that one of them is either NaN of +/-INFINITY
  2090. | Check for NaN (if either one is NaN return NaN)
  2091.     cmpl    d4,d0        | check first a (d0)
  2092.     bhi    Lf$inop        
  2093.     cmpl    d4,d1        | check now b (d1)
  2094.     bhi    Lf$inop        
  2095. | Now comes the check for +/-INFINITY. We know that both are (maybe not
  2096. | finite) numbers, but we have to check if both are infinite whether we
  2097. | are adding or subtracting them.
  2098.     eorl    d3,d2        | to check sign bits
  2099.     bmi    1f
  2100.     movel    d0,d7
  2101.     andl    IMM (0x80000000),d7    | get (common) sign bit
  2102.     bra    Lf$infty
  2103. 1:
  2104. | We know one (or both) are infinite, so we test for equality between the
  2105. | two numbers (if they are equal they have to be infinite both, so we
  2106. | return NaN).
  2107.     cmpl    d1,d0        | are both infinite?
  2108.     beq    Lf$inop        | if so return NaN
  2109.  
  2110.     movel    d0,d7
  2111.     andl    IMM (0x80000000),d7 | get a's sign bit '
  2112.     cmpl    d4,d0        | test now for infinity
  2113.     beq    Lf$infty    | if a is INFINITY return with this sign
  2114.     bchg    IMM (31),d7    | else we know b is INFINITY and has
  2115.     bra    Lf$infty    | the opposite sign
  2116.  
  2117. |=============================================================================
  2118. |                             __mulsf3
  2119. |=============================================================================
  2120.  
  2121. | float __mulsf3(float, float);
  2122. SYM (__mulsf3):
  2123.     link    a6,IMM (0)
  2124.     moveml    d2-d7,sp@-
  2125.     movel    a6@(8),d0    | get a into d0
  2126.     movel    a6@(12),d1    | and b into d1
  2127.     movel    d0,d7        | d7 will hold the sign of the product
  2128.     eorl    d1,d7        |
  2129.     andl    IMM (0x80000000),d7
  2130.     movel    IMM (INFINITY),d6    | useful constant (+INFINITY)
  2131.     movel    d6,d5            | another (mask for fraction)
  2132.     notl    d5            |
  2133.     movel    IMM (0x00800000),d4    | this is to put hidden bit back
  2134.     bclr    IMM (31),d0        | get rid of a's sign bit '
  2135.     movel    d0,d2            |
  2136.     beq    Lmulsf$a$0        | branch if a is zero
  2137.     bclr    IMM (31),d1        | get rid of b's sign bit '
  2138.     movel    d1,d3        |
  2139.     beq    Lmulsf$b$0    | branch if b is zero
  2140.     cmpl    d6,d0        | is a big?
  2141.     bhi    Lmulsf$inop    | if a is NaN return NaN
  2142.     beq    Lmulsf$inf    | if a is INFINITY we have to check b
  2143.     cmpl    d6,d1        | now compare b with INFINITY
  2144.     bhi    Lmulsf$inop    | is b NaN?
  2145.     beq    Lmulsf$overflow | is b INFINITY?
  2146. | Here we have both numbers finite and nonzero (and with no sign bit).
  2147. | Now we get the exponents into d2 and d3.
  2148.     andl    d6,d2        | and isolate exponent in d2
  2149.     beq    Lmulsf$a$den    | if exponent is zero we have a denormalized
  2150.     andl    d5,d0        | and isolate fraction
  2151.     orl    d4,d0        | and put hidden bit back
  2152.     swap    d2        | I like exponents in the first byte
  2153.     lsrw    IMM (7),d2    | 
  2154. Lmulsf$1:            | number
  2155.     andl    d6,d3        |
  2156.     beq    Lmulsf$b$den    |
  2157.     andl    d5,d1        |
  2158.     orl    d4,d1        |
  2159.     swap    d3        |
  2160.     lsrw    IMM (7),d3    |
  2161. Lmulsf$2:            |
  2162.     addw    d3,d2        | add exponents
  2163.     subw    IMM (F_BIAS+1),d2 | and subtract bias (plus one)
  2164.  
  2165. | We are now ready to do the multiplication. The situation is as follows:
  2166. | both a and b have bit FLT_MANT_DIG-1 set (even if they were 
  2167. | denormalized to start with!), which means that in the product 
  2168. | bit 2*(FLT_MANT_DIG-1) (that is, bit 2*FLT_MANT_DIG-2-32 of the 
  2169. | high long) is set. 
  2170.  
  2171. | To do the multiplication let us move the number a little bit around ...
  2172.     movel    d1,d6        | second operand in d6
  2173.     movel    d0,d5        | first operand in d4-d5
  2174.     movel    IMM (0),d4
  2175.     movel    d4,d1        | the sums will go in d0-d1
  2176.     movel    d4,d0
  2177.  
  2178. | now bit FLT_MANT_DIG-1 becomes bit 31:
  2179.     lsll    IMM (31-FLT_MANT_DIG+1),d6        
  2180.  
  2181. | Start the loop (we loop #FLT_MANT_DIG times):
  2182.     movew    IMM (FLT_MANT_DIG-1),d3    
  2183. 1:    addl    d1,d1        | shift sum 
  2184.     addxl    d0,d0
  2185.     lsll    IMM (1),d6    | get bit bn
  2186.     bcc    2f        | if not set skip sum
  2187.     addl    d5,d1        | add a
  2188.     addxl    d4,d0
  2189. 2:    dbf    d3,1b        | loop back
  2190.  
  2191. | Now we have the product in d0-d1, with bit (FLT_MANT_DIG - 1) + FLT_MANT_DIG
  2192. | (mod 32) of d0 set. The first thing to do now is to normalize it so bit 
  2193. | FLT_MANT_DIG is set (to do the rounding).
  2194.     rorl    IMM (6),d1
  2195.     swap    d1
  2196.     movew    d1,d3
  2197.     andw    IMM (0x03ff),d3
  2198.     andw    IMM (0xfd00),d1
  2199.     lsll    IMM (8),d0
  2200.     addl    d0,d0
  2201.     addl    d0,d0
  2202.     orw    d3,d0
  2203.  
  2204.     movew    IMM (MULTIPLY),d5
  2205.     
  2206.     btst    IMM (FLT_MANT_DIG+1),d0
  2207.     beq    Lround$exit
  2208.     lsrl    IMM (1),d0
  2209.     roxrl    IMM (1),d1
  2210.     addw    IMM (1),d2
  2211.     bra    Lround$exit
  2212.  
  2213. Lmulsf$inop:
  2214.     movew    IMM (MULTIPLY),d5
  2215.     bra    Lf$inop
  2216.  
  2217. Lmulsf$overflow:
  2218.     movew    IMM (MULTIPLY),d5
  2219.     bra    Lf$overflow
  2220.  
  2221. Lmulsf$inf:
  2222.     movew    IMM (MULTIPLY),d5
  2223. | If either is NaN return NaN; else both are (maybe infinite) numbers, so
  2224. | return INFINITY with the correct sign (which is in d7).
  2225.     cmpl    d6,d1        | is b NaN?
  2226.     bhi    Lf$inop        | if so return NaN
  2227.     bra    Lf$overflow    | else return +/-INFINITY
  2228.  
  2229. | If either number is zero return zero, unless the other is +/-INFINITY, 
  2230. | or NaN, in which case we return NaN.
  2231. Lmulsf$b$0:
  2232. | Here d1 (==b) is zero.
  2233.     movel    d1,d0        | put b into d0 (just a zero)
  2234.     movel    a6@(8),d1    | get a again to check for non-finiteness
  2235.     bra    1f
  2236. Lmulsf$a$0:
  2237.     movel    a6@(12),d1    | get b again to check for non-finiteness
  2238. 1:    bclr    IMM (31),d1    | clear sign bit 
  2239.     cmpl    IMM (INFINITY),d1 | and check for a large exponent
  2240.     bge    Lf$inop        | if b is +/-INFINITY or NaN return NaN
  2241.     lea    SYM (_fpCCR),a0    | else return zero
  2242.     movew    IMM (0),a0@    | 
  2243.     moveml    sp@+,d2-d7    | 
  2244.     unlk    a6        | 
  2245.     rts            | 
  2246.  
  2247. | If a number is denormalized we put an exponent of 1 but do not put the 
  2248. | hidden bit back into the fraction; instead we shift left until bit 23
  2249. | (the hidden bit) is set, adjusting the exponent accordingly. We do this
  2250. | to ensure that the product of the fractions is close to 1.
  2251. Lmulsf$a$den:
  2252.     movel    IMM (1),d2
  2253.     andl    d5,d0
  2254. 1:    addl    d0,d0        | shift a left (until bit 23 is set)
  2255.     subw    IMM (1),d2    | and adjust exponent
  2256.     btst    IMM (FLT_MANT_DIG-1),d0
  2257.     bne    Lmulsf$1    |
  2258.     bra    1b        | else loop back
  2259.  
  2260. Lmulsf$b$den:
  2261.     movel    IMM (1),d3
  2262.     andl    d5,d1
  2263. 1:    addl    d1,d1        | shift b left until bit 23 is set
  2264.     subw    IMM (1),d3    | and adjust exponent
  2265.     btst    IMM (FLT_MANT_DIG-1),d1
  2266.     bne    Lmulsf$2    |
  2267.     bra    1b        | else loop back
  2268.  
  2269. |=============================================================================
  2270. |                             __divsf3
  2271. |=============================================================================
  2272.  
  2273. | float __divsf3(float, float);
  2274. SYM (__divsf3):
  2275.     link    a6,IMM (0)
  2276.     moveml    d2-d7,sp@-
  2277.     movel    a6@(8),d0        | get a into d0
  2278.     movel    a6@(12),d1        | and b into d1
  2279.     movel    d0,d7            | d7 will hold the sign of the result
  2280.     eorl    d1,d7            |
  2281.     andl    IMM (0x80000000),d7    | 
  2282.     movel    IMM (INFINITY),d6    | useful constant (+INFINITY)
  2283.     movel    d6,d5            | another (mask for fraction)
  2284.     notl    d5            |
  2285.     movel    IMM (0x00800000),d4    | this is to put hidden bit back
  2286.     bclr    IMM (31),d0        | get rid of a's sign bit '
  2287.     movel    d0,d2            |
  2288.     beq    Ldivsf$a$0        | branch if a is zero
  2289.     bclr    IMM (31),d1        | get rid of b's sign bit '
  2290.     movel    d1,d3            |
  2291.     beq    Ldivsf$b$0        | branch if b is zero
  2292.     cmpl    d6,d0            | is a big?
  2293.     bhi    Ldivsf$inop        | if a is NaN return NaN
  2294.     beq    Ldivsf$inf        | if a is INFINITY we have to check b
  2295.     cmpl    d6,d1            | now compare b with INFINITY 
  2296.     bhi    Ldivsf$inop        | if b is NaN return NaN
  2297.     beq    Ldivsf$underflow
  2298. | Here we have both numbers finite and nonzero (and with no sign bit).
  2299. | Now we get the exponents into d2 and d3 and normalize the numbers to
  2300. | ensure that the ratio of the fractions is close to 1. We do this by
  2301. | making sure that bit #FLT_MANT_DIG-1 (hidden bit) is set.
  2302.     andl    d6,d2        | and isolate exponent in d2
  2303.     beq    Ldivsf$a$den    | if exponent is zero we have a denormalized
  2304.     andl    d5,d0        | and isolate fraction
  2305.     orl    d4,d0        | and put hidden bit back
  2306.     swap    d2        | I like exponents in the first byte
  2307.     lsrw    IMM (7),d2    | 
  2308. Ldivsf$1:            | 
  2309.     andl    d6,d3        |
  2310.     beq    Ldivsf$b$den    |
  2311.     andl    d5,d1        |
  2312.     orl    d4,d1        |
  2313.     swap    d3        |
  2314.     lsrw    IMM (7),d3    |
  2315. Ldivsf$2:            |
  2316.     subw    d3,d2        | subtract exponents
  2317.      addw    IMM (F_BIAS),d2    | and add bias
  2318.  
  2319. | We are now ready to do the division. We have prepared things in such a way
  2320. | that the ratio of the fractions will be less than 2 but greater than 1/2.
  2321. | At this point the registers in use are:
  2322. | d0    holds a (first operand, bit FLT_MANT_DIG=0, bit FLT_MANT_DIG-1=1)
  2323. | d1    holds b (second operand, bit FLT_MANT_DIG=1)
  2324. | d2    holds the difference of the exponents, corrected by the bias
  2325. | d7    holds the sign of the ratio
  2326. | d4, d5, d6 hold some constants
  2327.     movel    d7,a0        | d6-d7 will hold the ratio of the fractions
  2328.     movel    IMM (0),d6    | 
  2329.     movel    d6,d7
  2330.  
  2331.     movew    IMM (FLT_MANT_DIG+1),d3
  2332. 1:    cmpl    d0,d1        | is a < b?
  2333.     bhi    2f        |
  2334.     bset    d3,d6        | set a bit in d6
  2335.     subl    d1,d0        | if a >= b  a <-- a-b
  2336.     beq    3f        | if a is zero, exit
  2337. 2:    addl    d0,d0        | multiply a by 2
  2338.     dbra    d3,1b
  2339.  
  2340. | Now we keep going to set the sticky bit ...
  2341.     movew    IMM (FLT_MANT_DIG),d3
  2342. 1:    cmpl    d0,d1
  2343.     ble    2f
  2344.     addl    d0,d0
  2345.     dbra    d3,1b
  2346.     movel    IMM (0),d1
  2347.     bra    3f
  2348. 2:    movel    IMM (0),d1
  2349.     subw    IMM (FLT_MANT_DIG),d3
  2350.     addw    IMM (31),d3
  2351.     bset    d3,d1
  2352. 3:
  2353.     movel    d6,d0        | put the ratio in d0-d1
  2354.     movel    a0,d7        | get sign back
  2355.  
  2356. | Because of the normalization we did before we are guaranteed that 
  2357. | d0 is smaller than 2^26 but larger than 2^24. Thus bit 26 is not set,
  2358. | bit 25 could be set, and if it is not set then bit 24 is necessarily set.
  2359.     btst    IMM (FLT_MANT_DIG+1),d0        
  2360.     beq    1f              | if it is not set, then bit 24 is set
  2361.     lsrl    IMM (1),d0    |
  2362.     addw    IMM (1),d2    |
  2363. 1:
  2364. | Now round, check for over- and underflow, and exit.
  2365.     movew    IMM (DIVIDE),d5
  2366.     bra    Lround$exit
  2367.  
  2368. Ldivsf$inop:
  2369.     movew    IMM (DIVIDE),d5
  2370.     bra    Lf$inop
  2371.  
  2372. Ldivsf$overflow:
  2373.     movew    IMM (DIVIDE),d5
  2374.     bra    Lf$overflow
  2375.  
  2376. Ldivsf$underflow:
  2377.     movew    IMM (DIVIDE),d5
  2378.     bra    Lf$underflow
  2379.  
  2380. Ldivsf$a$0:
  2381.     movew    IMM (DIVIDE),d5
  2382. | If a is zero check to see whether b is zero also. In that case return
  2383. | NaN; then check if b is NaN, and return NaN also in that case. Else
  2384. | return zero.
  2385.     andl    IMM (0x7fffffff),d1    | clear sign bit and test b
  2386.     beq    Lf$inop            | if b is also zero return NaN
  2387.     cmpl    IMM (INFINITY),d1    | check for NaN
  2388.     bhi    Lf$inop            | 
  2389.     movel    IMM (0),d0        | else return zero
  2390.     lea    SYM (_fpCCR),a0        |
  2391.     movew    IMM (0),a0@        |
  2392.     moveml    sp@+,d2-d7        | 
  2393.     unlk    a6            | 
  2394.     rts                | 
  2395.     
  2396. Ldivsf$b$0:
  2397.     movew    IMM (DIVIDE),d5
  2398. | If we got here a is not zero. Check if a is NaN; in that case return NaN,
  2399. | else return +/-INFINITY. Remember that a is in d0 with the sign bit 
  2400. | cleared already.
  2401.     cmpl    IMM (INFINITY),d0    | compare d0 with INFINITY
  2402.     bhi    Lf$inop            | if larger it is NaN
  2403.     bra    Lf$div$0        | else signal DIVIDE_BY_ZERO
  2404.  
  2405. Ldivsf$inf:
  2406.     movew    IMM (DIVIDE),d5
  2407. | If a is INFINITY we have to check b
  2408.     cmpl    IMM (INFINITY),d1    | compare b with INFINITY 
  2409.     bge    Lf$inop            | if b is NaN or INFINITY return NaN
  2410.     bra    Lf$overflow        | else return overflow
  2411.  
  2412. | If a number is denormalized we put an exponent of 1 but do not put the 
  2413. | bit back into the fraction.
  2414. Ldivsf$a$den:
  2415.     movel    IMM (1),d2
  2416.     andl    d5,d0
  2417. 1:    addl    d0,d0        | shift a left until bit FLT_MANT_DIG-1 is set
  2418.     subw    IMM (1),d2    | and adjust exponent
  2419.     btst    IMM (FLT_MANT_DIG-1),d0
  2420.     bne    Ldivsf$1
  2421.     bra    1b
  2422.  
  2423. Ldivsf$b$den:
  2424.     movel    IMM (1),d3
  2425.     andl    d5,d1
  2426. 1:    addl    d1,d1        | shift b left until bit FLT_MANT_DIG is set
  2427.     subw    IMM (1),d3    | and adjust exponent
  2428.     btst    IMM (FLT_MANT_DIG-1),d1
  2429.     bne    Ldivsf$2
  2430.     bra    1b
  2431.  
  2432. Lround$exit:
  2433. | This is a common exit point for __mulsf3 and __divsf3. 
  2434.  
  2435. | First check for underlow in the exponent:
  2436.     cmpw    IMM (-FLT_MANT_DIG-1),d2        
  2437.     blt    Lf$underflow    
  2438. | It could happen that the exponent is less than 1, in which case the 
  2439. | number is denormalized. In this case we shift right and adjust the 
  2440. | exponent until it becomes 1 or the fraction is zero (in the latter case 
  2441. | we signal underflow and return zero).
  2442.     movel    IMM (0),d6    | d6 is used temporarily
  2443.     cmpw    IMM (1),d2    | if the exponent is less than 1 we 
  2444.     bge    2f        | have to shift right (denormalize)
  2445. 1:    addw    IMM (1),d2    | adjust the exponent
  2446.     lsrl    IMM (1),d0    | shift right once 
  2447.     roxrl    IMM (1),d1    |
  2448.     roxrl    IMM (1),d6    | d6 collect bits we would lose otherwise
  2449.     cmpw    IMM (1),d2    | is the exponent 1 already?
  2450.     beq    2f        | if not loop back
  2451.     bra    1b              |
  2452.     bra    Lf$underflow    | safety check, shouldn't execute '
  2453. 2:    orl    d6,d1        | this is a trick so we don't lose  '
  2454.                 | the extra bits which were flushed right
  2455. | Now call the rounding routine (which takes care of denormalized numbers):
  2456.     lea    Lround$0,a0    | to return from rounding routine
  2457.     lea    SYM (_fpCCR),a1    | check the rounding mode
  2458.     movew    a1@(6),d6    | rounding mode in d6
  2459.     beq    Lround$to$nearest
  2460.     cmpw    IMM (ROUND_TO_PLUS),d6
  2461.     bhi    Lround$to$minus
  2462.     blt    Lround$to$zero
  2463.     bra    Lround$to$plus
  2464. Lround$0:
  2465. | Here we have a correctly rounded result (either normalized or denormalized).
  2466.  
  2467. | Here we should have either a normalized number or a denormalized one, and
  2468. | the exponent is necessarily larger or equal to 1 (so we don't have to  '
  2469. | check again for underflow!). We have to check for overflow or for a 
  2470. | denormalized number (which also signals underflow).
  2471. | Check for overflow (i.e., exponent >= 255).
  2472.     cmpw    IMM (0x00ff),d2
  2473.     bge    Lf$overflow
  2474. | Now check for a denormalized number (exponent==0).
  2475.     movew    d2,d2
  2476.     beq    Lf$den
  2477. 1:
  2478. | Put back the exponents and sign and return.
  2479.     lslw    IMM (7),d2    | exponent back to fourth byte
  2480.     bclr    IMM (FLT_MANT_DIG-1),d0
  2481.     swap    d0        | and put back exponent
  2482.     orw    d2,d0        | 
  2483.     swap    d0        |
  2484.     orl    d7,d0        | and sign also
  2485.  
  2486.     lea    SYM (_fpCCR),a0
  2487.     movew    IMM (0),a0@
  2488.     moveml    sp@+,d2-d7
  2489.     unlk    a6
  2490.     rts
  2491.  
  2492. |=============================================================================
  2493. |                             __negsf2
  2494. |=============================================================================
  2495.  
  2496. | This is trivial and could be shorter if we didn't bother checking for NaN '
  2497. | and +/-INFINITY.
  2498.  
  2499. | float __negsf2(float);
  2500. SYM (__negsf2):
  2501.     link    a6,IMM (0)
  2502.     moveml    d2-d7,sp@-
  2503.     movew    IMM (NEGATE),d5
  2504.     movel    a6@(8),d0    | get number to negate in d0
  2505.     bchg    IMM (31),d0    | negate
  2506.     movel    d0,d1        | make a positive copy
  2507.     bclr    IMM (31),d1    |
  2508.     tstl    d1        | check for zero
  2509.     beq    2f        | if zero (either sign) return +zero
  2510.     cmpl    IMM (INFINITY),d1 | compare to +INFINITY
  2511.     blt    1f        |
  2512.     bhi    Lf$inop        | if larger (fraction not zero) is NaN
  2513.     movel    d0,d7        | else get sign and return INFINITY
  2514.     andl    IMM (0x80000000),d7
  2515.     bra    Lf$infty        
  2516. 1:    lea    SYM (_fpCCR),a0
  2517.     movew    IMM (0),a0@
  2518.     moveml    sp@+,d2-d7
  2519.     unlk    a6
  2520.     rts
  2521. 2:    bclr    IMM (31),d0
  2522.     bra    1b
  2523.  
  2524. |=============================================================================
  2525. |                             __cmpsf2
  2526. |=============================================================================
  2527.  
  2528. GREATER =  1
  2529. LESS    = -1
  2530. EQUAL   =  0
  2531.  
  2532. | int __cmpsf2(float, float);
  2533. SYM (__cmpsf2):
  2534.     link    a6,IMM (0)
  2535.     moveml    d2-d7,sp@-     | save registers
  2536.     movew    IMM (COMPARE),d5
  2537.     movel    a6@(8),d0    | get first operand
  2538.     movel    a6@(12),d1    | get second operand
  2539. | Check if either is NaN, and in that case return garbage and signal
  2540. | INVALID_OPERATION. Check also if either is zero, and clear the signs
  2541. | if necessary.
  2542.     movel    d0,d6
  2543.     andl    IMM (0x7fffffff),d0
  2544.     beq    Lcmpsf$a$0
  2545.     cmpl    IMM (0x7f800000),d0
  2546.     bhi    Lf$inop
  2547. Lcmpsf$1:
  2548.     movel    d1,d7
  2549.     andl    IMM (0x7fffffff),d1
  2550.     beq    Lcmpsf$b$0
  2551.     cmpl    IMM (0x7f800000),d1
  2552.     bhi    Lf$inop
  2553. Lcmpsf$2:
  2554. | Check the signs
  2555.     eorl    d6,d7
  2556.     bpl    1f
  2557. | If the signs are not equal check if a >= 0
  2558.     tstl    d6
  2559.     bpl    Lcmpsf$a$gt$b    | if (a >= 0 && b < 0) => a > b
  2560.     bmi    Lcmpsf$b$gt$a    | if (a < 0 && b >= 0) => a < b
  2561. 1:
  2562. | If the signs are equal check for < 0
  2563.     tstl    d6
  2564.     bpl    1f
  2565. | If both are negative exchange them
  2566.     exg    d0,d1
  2567. 1:
  2568. | Now that they are positive we just compare them as longs (does this also
  2569. | work for denormalized numbers?).
  2570.     cmpl    d0,d1
  2571.     bhi    Lcmpsf$b$gt$a    | |b| > |a|
  2572.     bne    Lcmpsf$a$gt$b    | |b| < |a|
  2573. | If we got here a == b.
  2574.     movel    IMM (EQUAL),d0
  2575.     moveml    sp@+,d2-d7     | put back the registers
  2576.     unlk    a6
  2577.     rts
  2578. Lcmpsf$a$gt$b:
  2579.     movel    IMM (GREATER),d0
  2580.     moveml    sp@+,d2-d7     | put back the registers
  2581.     unlk    a6
  2582.     rts
  2583. Lcmpsf$b$gt$a:
  2584.     movel    IMM (LESS),d0
  2585.     moveml    sp@+,d2-d7     | put back the registers
  2586.     unlk    a6
  2587.     rts
  2588.  
  2589. Lcmpsf$a$0:    
  2590.     bclr    IMM (31),d6
  2591.     bra    Lcmpsf$1
  2592. Lcmpsf$b$0:
  2593.     bclr    IMM (31),d7
  2594.     bra    Lcmpsf$2
  2595.  
  2596. |=============================================================================
  2597. |                           rounding routines
  2598. |=============================================================================
  2599.  
  2600. | The rounding routines expect the number to be normalized in registers
  2601. | d0-d1, with the exponent in register d2. They assume that the 
  2602. | exponent is larger or equal to 1. They return a properly normalized number
  2603. | if possible, and a denormalized number otherwise. The exponent is returned
  2604. | in d2.
  2605.  
  2606. Lround$to$nearest:
  2607. | We now normalize as suggested by D. Knuth ("Seminumerical Algorithms"):
  2608. | Here we assume that the exponent is not too small (this should be checked
  2609. | before entering the rounding routine), but the number could be denormalized.
  2610.  
  2611. | Check for denormalized numbers:
  2612. 1:    btst    IMM (FLT_MANT_DIG),d0
  2613.     bne    2f        | if set the number is normalized
  2614. | Normalize shifting left until bit #FLT_MANT_DIG is set or the exponent 
  2615. | is one (remember that a denormalized number corresponds to an 
  2616. | exponent of -F_BIAS+1).
  2617.     cmpw    IMM (1),d2    | remember that the exponent is at least one
  2618.      beq    2f        | an exponent of one means denormalized
  2619.     addl    d1,d1        | else shift and adjust the exponent
  2620.     addxl    d0,d0        |
  2621.     dbra    d2,1b        |
  2622. 2:
  2623. | Now round: we do it as follows: after the shifting we can write the
  2624. | fraction part as f + delta, where 1 < f < 2^25, and 0 <= delta <= 2.
  2625. | If delta < 1, do nothing. If delta > 1, add 1 to f. 
  2626. | If delta == 1, we make sure the rounded number will be even (odd?) 
  2627. | (after shifting).
  2628.     btst    IMM (0),d0    | is delta < 1?
  2629.     beq    2f        | if so, do not do anything
  2630.     tstl    d1        | is delta == 1?
  2631.     bne    1f        | if so round to even
  2632.     movel    d0,d1        | 
  2633.     andl    IMM (2),d1    | bit 1 is the last significant bit
  2634.     addl    d1,d0        | 
  2635.     bra    2f        | 
  2636. 1:    movel    IMM (1),d1    | else add 1 
  2637.     addl    d1,d0        |
  2638. | Shift right once (because we used bit #FLT_MANT_DIG!).
  2639. 2:    lsrl    IMM (1),d0        
  2640. | Now check again bit #FLT_MANT_DIG (rounding could have produced a
  2641. | 'fraction overflow' ...).
  2642.     btst    IMM (FLT_MANT_DIG),d0    
  2643.     beq    1f
  2644.     lsrl    IMM (1),d0
  2645.     addw    IMM (1),d2
  2646. 1:
  2647. | If bit #FLT_MANT_DIG-1 is clear we have a denormalized number, so we 
  2648. | have to put the exponent to zero and return a denormalized number.
  2649.     btst    IMM (FLT_MANT_DIG-1),d0
  2650.     beq    1f
  2651.     jmp    a0@
  2652. 1:    movel    IMM (0),d2
  2653.     jmp    a0@
  2654.  
  2655. Lround$to$zero:
  2656. Lround$to$plus:
  2657. Lround$to$minus:
  2658.     jmp    a0@
  2659. #endif /* L_float */
  2660.  
  2661. | gcc expects the routines __eqdf2, __nedf2, __gtdf2, __gedf2,
  2662. | __ledf2, __ltdf2 to all return the same value as a direct call to
  2663. | __cmpdf2 would.  In this implementation, each of these routines
  2664. | simply calls __cmpdf2.  It would be more efficient to give the
  2665. | __cmpdf2 routine several names, but separating them out will make it
  2666. | easier to write efficient versions of these routines someday.
  2667.  
  2668. #ifdef  L_eqdf2
  2669. LL0:
  2670.     .text
  2671.     .proc
  2672. |#PROC# 04
  2673.     LF18    =    4
  2674.     LS18    =    128
  2675.     LFF18    =    0
  2676.     LSS18    =    0
  2677.     LV18    =    0
  2678.     .text
  2679.     .globl    SYM (__eqdf2)
  2680. SYM (__eqdf2):
  2681. |#PROLOGUE# 0
  2682.     link    a6,IMM (0)
  2683. |#PROLOGUE# 1
  2684.     movl    a6@(20),sp@-
  2685.     movl    a6@(16),sp@-
  2686.     movl    a6@(12),sp@-
  2687.     movl    a6@(8),sp@-
  2688.     jbsr    SYM (__cmpdf2)
  2689. |#PROLOGUE# 2
  2690.     unlk    a6
  2691. |#PROLOGUE# 3
  2692.     rts
  2693. #endif /* L_eqdf2 */
  2694.  
  2695. #ifdef  L_nedf2
  2696. LL0:
  2697.     .text
  2698.     .proc
  2699. |#PROC# 04
  2700.     LF18    =    8
  2701.     LS18    =    132
  2702.     LFF18    =    0
  2703.     LSS18    =    0
  2704.     LV18    =    0
  2705.     .text
  2706.     .globl    SYM (__nedf2)
  2707. SYM (__nedf2):
  2708. |#PROLOGUE# 0
  2709.     link    a6,IMM (0)
  2710. |#PROLOGUE# 1
  2711.     movl    a6@(20),sp@-
  2712.     movl    a6@(16),sp@-
  2713.     movl    a6@(12),sp@-
  2714.     movl    a6@(8),sp@-
  2715.     jbsr    SYM (__cmpdf2)
  2716. |#PROLOGUE# 2
  2717.     unlk    a6
  2718. |#PROLOGUE# 3
  2719.     rts
  2720. #endif /* L_nedf2 */
  2721.  
  2722. #ifdef  L_gtdf2
  2723.     .text
  2724.     .proc
  2725. |#PROC# 04
  2726.     LF18    =    8
  2727.     LS18    =    132
  2728.     LFF18    =    0
  2729.     LSS18    =    0
  2730.     LV18    =    0
  2731.     .text
  2732.     .globl    SYM (__gtdf2)
  2733. SYM (__gtdf2):
  2734. |#PROLOGUE# 0
  2735.     link    a6,IMM (0)
  2736. |#PROLOGUE# 1
  2737.     movl    a6@(20),sp@-
  2738.     movl    a6@(16),sp@-
  2739.     movl    a6@(12),sp@-
  2740.     movl    a6@(8),sp@-
  2741.     jbsr    SYM (__cmpdf2)
  2742. |#PROLOGUE# 2
  2743.     unlk    a6
  2744. |#PROLOGUE# 3
  2745.     rts
  2746. #endif /* L_gtdf2 */
  2747.  
  2748. #ifdef  L_gedf2
  2749. LL0:
  2750.     .text
  2751.     .proc
  2752. |#PROC# 04
  2753.     LF18    =    8
  2754.     LS18    =    132
  2755.     LFF18    =    0
  2756.     LSS18    =    0
  2757.     LV18    =    0
  2758.     .text
  2759.     .globl    SYM (__gedf2)
  2760. SYM (__gedf2):
  2761. |#PROLOGUE# 0
  2762.     link    a6,IMM (0)
  2763. |#PROLOGUE# 1
  2764.     movl    a6@(20),sp@-
  2765.     movl    a6@(16),sp@-
  2766.     movl    a6@(12),sp@-
  2767.     movl    a6@(8),sp@-
  2768.     jbsr    SYM (__cmpdf2)
  2769. |#PROLOGUE# 2
  2770.     unlk    a6
  2771. |#PROLOGUE# 3
  2772.     rts
  2773. #endif /* L_gedf2 */
  2774.  
  2775. #ifdef  L_ltdf2
  2776. LL0:
  2777.     .text
  2778.     .proc
  2779. |#PROC# 04
  2780.     LF18    =    8
  2781.     LS18    =    132
  2782.     LFF18    =    0
  2783.     LSS18    =    0
  2784.     LV18    =    0
  2785.     .text
  2786.     .globl    SYM (__ltdf2)
  2787. SYM (__ltdf2):
  2788. |#PROLOGUE# 0
  2789.     link    a6,IMM (0)
  2790. |#PROLOGUE# 1
  2791.     movl    a6@(20),sp@-
  2792.     movl    a6@(16),sp@-
  2793.     movl    a6@(12),sp@-
  2794.     movl    a6@(8),sp@-
  2795.     jbsr    SYM (__cmpdf2)
  2796. |#PROLOGUE# 2
  2797.     unlk    a6
  2798. |#PROLOGUE# 3
  2799.     rts
  2800. #endif /* L_ltdf2 */
  2801.  
  2802. #ifdef  L_ledf2
  2803.     .text
  2804.     .proc
  2805. |#PROC# 04
  2806.     LF18    =    8
  2807.     LS18    =    132
  2808.     LFF18    =    0
  2809.     LSS18    =    0
  2810.     LV18    =    0
  2811.     .text
  2812.     .globl    SYM (__ledf2)
  2813. SYM (__ledf2):
  2814. |#PROLOGUE# 0
  2815.     link    a6,IMM (0)
  2816. |#PROLOGUE# 1
  2817.     movl    a6@(20),sp@-
  2818.     movl    a6@(16),sp@-
  2819.     movl    a6@(12),sp@-
  2820.     movl    a6@(8),sp@-
  2821.     jbsr    SYM (__cmpdf2)
  2822. |#PROLOGUE# 2
  2823.     unlk    a6
  2824. |#PROLOGUE# 3
  2825.     rts
  2826. #endif /* L_ledf2 */
  2827.  
  2828. | The comments above about __eqdf2, et. al., also apply to __eqsf2,
  2829. | et. al., except that the latter call __cmpsf2 rather than __cmpdf2.
  2830.  
  2831. #ifdef  L_eqsf2
  2832.     .text
  2833.     .proc
  2834. |#PROC# 04
  2835.     LF18    =    4
  2836.     LS18    =    128
  2837.     LFF18    =    0
  2838.     LSS18    =    0
  2839.     LV18    =    0
  2840.     .text
  2841.     .globl    SYM (__eqsf2)
  2842. SYM (__eqsf2):
  2843. |#PROLOGUE# 0
  2844.     link    a6,IMM (0)
  2845. |#PROLOGUE# 1
  2846.     movl    a6@(12),sp@-
  2847.     movl    a6@(8),sp@-
  2848.     jbsr    SYM (__cmpsf2)
  2849. |#PROLOGUE# 2
  2850.     unlk    a6
  2851. |#PROLOGUE# 3
  2852.     rts
  2853. #endif /* L_eqsf2 */
  2854.  
  2855. #ifdef  L_nesf2
  2856.     .text
  2857.     .proc
  2858. |#PROC# 04
  2859.     LF18    =    8
  2860.     LS18    =    132
  2861.     LFF18    =    0
  2862.     LSS18    =    0
  2863.     LV18    =    0
  2864.     .text
  2865.     .globl    SYM (__nesf2)
  2866. SYM (__nesf2):
  2867. |#PROLOGUE# 0
  2868.     link    a6,IMM (0)
  2869. |#PROLOGUE# 1
  2870.     movl    a6@(12),sp@-
  2871.     movl    a6@(8),sp@-
  2872.     jbsr    SYM (__cmpsf2)
  2873. |#PROLOGUE# 2
  2874.     unlk    a6
  2875. |#PROLOGUE# 3
  2876.     rts
  2877. #endif /* L_nesf2 */
  2878.  
  2879. #ifdef  L_gtsf2
  2880.     .text
  2881.     .proc
  2882. |#PROC# 04
  2883.     LF18    =    8
  2884.     LS18    =    132
  2885.     LFF18    =    0
  2886.     LSS18    =    0
  2887.     LV18    =    0
  2888.     .text
  2889.     .globl    SYM (__gtsf2)
  2890. SYM (__gtsf2):
  2891. |#PROLOGUE# 0
  2892.     link    a6,IMM (0)
  2893. |#PROLOGUE# 1
  2894.     movl    a6@(12),sp@-
  2895.     movl    a6@(8),sp@-
  2896.     jbsr    SYM (__cmpsf2)
  2897. |#PROLOGUE# 2
  2898.     unlk    a6
  2899. |#PROLOGUE# 3
  2900.     rts
  2901. #endif /* L_gtsf2 */
  2902.  
  2903. #ifdef  L_gesf2
  2904.     .text
  2905.     .proc
  2906. |#PROC# 04
  2907.     LF18    =    8
  2908.     LS18    =    132
  2909.     LFF18    =    0
  2910.     LSS18    =    0
  2911.     LV18    =    0
  2912.     .text
  2913.     .globl    SYM (__gesf2)
  2914. SYM (__gesf2):
  2915. |#PROLOGUE# 0
  2916.     link    a6,IMM (0)
  2917. |#PROLOGUE# 1
  2918.     movl    a6@(12),sp@-
  2919.     movl    a6@(8),sp@-
  2920.     jbsr    SYM (__cmpsf2)
  2921. |#PROLOGUE# 2
  2922.     unlk    a6
  2923. |#PROLOGUE# 3
  2924.     rts
  2925. #endif /* L_gesf2 */
  2926.  
  2927. #ifdef  L_ltsf2
  2928.     .text
  2929.     .proc
  2930. |#PROC# 04
  2931.     LF18    =    8
  2932.     LS18    =    132
  2933.     LFF18    =    0
  2934.     LSS18    =    0
  2935.     LV18    =    0
  2936.     .text
  2937.     .globl    SYM (__ltsf2)
  2938. SYM (__ltsf2):
  2939. |#PROLOGUE# 0
  2940.     link    a6,IMM (0)
  2941. |#PROLOGUE# 1
  2942.     movl    a6@(12),sp@-
  2943.     movl    a6@(8),sp@-
  2944.     jbsr    SYM (__cmpsf2)
  2945. |#PROLOGUE# 2
  2946.     unlk    a6
  2947. |#PROLOGUE# 3
  2948.     rts
  2949. #endif /* L_ltsf2 */
  2950.  
  2951. #ifdef  L_lesf2
  2952.     .text
  2953.     .proc
  2954. |#PROC# 04
  2955.     LF18    =    8
  2956.     LS18    =    132
  2957.     LFF18    =    0
  2958.     LSS18    =    0
  2959.     LV18    =    0
  2960.     .text
  2961.     .globl    SYM (__lesf2)
  2962. SYM (__lesf2):
  2963. |#PROLOGUE# 0
  2964.     link    a6,IMM (0)
  2965. |#PROLOGUE# 1
  2966.     movl    a6@(12),sp@-
  2967.     movl    a6@(8),sp@-
  2968.     jbsr    SYM (__cmpsf2)
  2969. |#PROLOGUE# 2
  2970.     unlk    a6
  2971. |#PROLOGUE# 3
  2972.     rts
  2973. #endif /* L_lesf2 */
  2974.  
  2975.